summaryrefslogtreecommitdiff
path: root/platform/osx
diff options
context:
space:
mode:
Diffstat (limited to 'platform/osx')
-rw-r--r--platform/osx/SCsub2
-rw-r--r--platform/osx/context_gl_osx.mm161
-rw-r--r--platform/osx/crash_handler_osx.mm7
-rw-r--r--platform/osx/detect.py20
-rw-r--r--platform/osx/display_server_osx.h24
-rw-r--r--platform/osx/display_server_osx.mm623
-rw-r--r--platform/osx/export/export_plugin.cpp96
-rw-r--r--platform/osx/export/export_plugin.h2
-rw-r--r--platform/osx/gl_manager_osx.h (renamed from platform/osx/context_gl_osx.h)74
-rw-r--r--platform/osx/gl_manager_osx.mm233
-rw-r--r--platform/osx/joypad_osx.cpp43
-rw-r--r--platform/osx/joypad_osx.h5
-rw-r--r--platform/osx/os_osx.h5
-rw-r--r--platform/osx/os_osx.mm123
-rw-r--r--platform/osx/platform_config.h1
15 files changed, 870 insertions, 549 deletions
diff --git a/platform/osx/SCsub b/platform/osx/SCsub
index 46c13d8550..8ba106d1c2 100644
--- a/platform/osx/SCsub
+++ b/platform/osx/SCsub
@@ -13,7 +13,7 @@ files = [
"dir_access_osx.mm",
"joypad_osx.cpp",
"vulkan_context_osx.mm",
- "context_gl_osx.mm",
+ "gl_manager_osx.mm",
]
prog = env.add_program("#bin/godot", files)
diff --git a/platform/osx/context_gl_osx.mm b/platform/osx/context_gl_osx.mm
deleted file mode 100644
index 88db1a296e..0000000000
--- a/platform/osx/context_gl_osx.mm
+++ /dev/null
@@ -1,161 +0,0 @@
-/*************************************************************************/
-/* context_gl_osx.mm */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* https://godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
-/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
-/* */
-/* Permission is hereby granted, free of charge, to any person obtaining */
-/* a copy of this software and associated documentation files (the */
-/* "Software"), to deal in the Software without restriction, including */
-/* without limitation the rights to use, copy, modify, merge, publish, */
-/* distribute, sublicense, and/or sell copies of the Software, and to */
-/* permit persons to whom the Software is furnished to do so, subject to */
-/* the following conditions: */
-/* */
-/* The above copyright notice and this permission notice shall be */
-/* included in all copies or substantial portions of the Software. */
-/* */
-/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
-/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
-/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
-/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
-/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
-/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
-/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
-/*************************************************************************/
-
-#include "context_gl_osx.h"
-
-#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED)
-
-void ContextGL_OSX::release_current() {
- [NSOpenGLContext clearCurrentContext];
-}
-
-void ContextGL_OSX::make_current() {
- [context makeCurrentContext];
-}
-
-void ContextGL_OSX::update() {
- [context update];
-}
-
-void ContextGL_OSX::set_opacity(GLint p_opacity) {
- [context setValues:&p_opacity forParameter:NSOpenGLCPSurfaceOpacity];
-}
-
-int ContextGL_OSX::get_window_width() {
- return OS::get_singleton()->get_video_mode().width;
-}
-
-int ContextGL_OSX::get_window_height() {
- return OS::get_singleton()->get_video_mode().height;
-}
-
-void ContextGL_OSX::swap_buffers() {
- [context flushBuffer];
-}
-
-void ContextGL_OSX::set_use_vsync(bool p_use) {
- CGLContextObj ctx = CGLGetCurrentContext();
- if (ctx) {
- GLint swapInterval = p_use ? 1 : 0;
- CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval);
- use_vsync = p_use;
- }
-}
-
-bool ContextGL_OSX::is_using_vsync() const {
- return use_vsync;
-}
-
-Error ContextGL_OSX::initialize() {
- framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
- ERR_FAIL_COND_V(!framework, ERR_CANT_CREATE);
-
- unsigned int attributeCount = 0;
-
- // OS X needs non-zero color size, so set reasonable values
- int colorBits = 32;
-
- // Fail if a robustness strategy was requested
-
-#define ADD_ATTR(x) \
- { attributes[attributeCount++] = x; }
-#define ADD_ATTR2(x, y) \
- { \
- ADD_ATTR(x); \
- ADD_ATTR(y); \
- }
-
- // Arbitrary array size here
- NSOpenGLPixelFormatAttribute attributes[40];
-
- ADD_ATTR(NSOpenGLPFADoubleBuffer);
- ADD_ATTR(NSOpenGLPFAClosestPolicy);
-
- if (!opengl_3_context) {
- ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersionLegacy);
- } else {
- //we now need OpenGL 3 or better, maybe even change this to 3_3Core ?
- ADD_ATTR2(NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core);
- }
-
- ADD_ATTR2(NSOpenGLPFAColorSize, colorBits);
-
- /*
- if (fbconfig->alphaBits > 0)
- ADD_ATTR2(NSOpenGLPFAAlphaSize, fbconfig->alphaBits);
-*/
-
- ADD_ATTR2(NSOpenGLPFADepthSize, 24);
-
- ADD_ATTR2(NSOpenGLPFAStencilSize, 8);
-
- /*
- if (fbconfig->stereo)
- ADD_ATTR(NSOpenGLPFAStereo);
-*/
-
- /*
- if (fbconfig->samples > 0) {
- ADD_ATTR2(NSOpenGLPFASampleBuffers, 1);
- ADD_ATTR2(NSOpenGLPFASamples, fbconfig->samples);
- }
-*/
-
- // NOTE: All NSOpenGLPixelFormats on the relevant cards support sRGB
- // framebuffer, so there's no need (and no way) to request it
-
- ADD_ATTR(0);
-
-#undef ADD_ATTR
-#undef ADD_ATTR2
-
- pixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
- ERR_FAIL_COND_V(pixelFormat == nil, ERR_CANT_CREATE);
-
- context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:nil];
-
- ERR_FAIL_COND_V(context == nil, ERR_CANT_CREATE);
-
- [context setView:window_view];
-
- [context makeCurrentContext];
-
- return OK;
-}
-
-ContextGL_OSX::ContextGL_OSX(id p_view, bool p_opengl_3_context) {
- opengl_3_context = p_opengl_3_context;
- window_view = p_view;
- use_vsync = false;
-}
-
-ContextGL_OSX::~ContextGL_OSX() {}
-
-#endif
diff --git a/platform/osx/crash_handler_osx.mm b/platform/osx/crash_handler_osx.mm
index 31228b10b4..57bca7a5b9 100644
--- a/platform/osx/crash_handler_osx.mm
+++ b/platform/osx/crash_handler_osx.mm
@@ -134,8 +134,13 @@ static void handle_crash(int sig) {
args.push_back("-o");
args.push_back(_execpath);
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64__)
args.push_back("-arch");
args.push_back("x86_64");
+#elif defined(__aarch64__)
+ args.push_back("-arch");
+ args.push_back("arm64");
+#endif
args.push_back("-l");
snprintf(str, 1024, "%p", load_addr);
args.push_back(str);
@@ -146,7 +151,7 @@ static void handle_crash(int sig) {
String out = "";
Error err = OS::get_singleton()->execute(String("atos"), args, &out, &ret);
if (err == OK && out.substr(0, 2) != "0x") {
- out.erase(out.length() - 1, 1);
+ out = out.substr(0, out.length() - 1);
output = out;
}
}
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 6b25daf05d..c67791b340 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -31,6 +31,7 @@ def get_opts():
BoolVariable("use_ubsan", "Use LLVM/GCC compiler undefined behavior sanitizer (UBSAN)", False),
BoolVariable("use_asan", "Use LLVM/GCC compiler address sanitizer (ASAN)", False),
BoolVariable("use_tsan", "Use LLVM/GCC compiler thread sanitizer (TSAN)", False),
+ BoolVariable("use_coverage", "Use instrumentation codes in the binary (e.g. for code coverage)", False),
]
@@ -57,13 +58,11 @@ def configure(env):
env.Prepend(CCFLAGS=["-O2"])
elif env["optimize"] == "size": # optimize for size
env.Prepend(CCFLAGS=["-Os"])
- env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])
if env["debug_symbols"]:
env.Prepend(CCFLAGS=["-g2"])
elif env["target"] == "debug":
env.Prepend(CCFLAGS=["-g3"])
- env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])
env.Prepend(LINKFLAGS=["-Xlinker", "-no_deduplicate"])
## Architecture
@@ -83,7 +82,7 @@ def configure(env):
env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15"])
env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15"])
else:
- print("Building for macOS 10.12+, platform x86-64.")
+ print("Building for macOS 10.12+, platform x86_64.")
env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
env.Append(LINKFLAGS=["-arch", "x86_64", "-mmacosx-version-min=10.12"])
@@ -96,7 +95,6 @@ def configure(env):
env["AR"] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-ar"
env["RANLIB"] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-ranlib"
env["AS"] = mpprefix + "/libexec/llvm-" + mpclangver + "/bin/llvm-as"
- env.Append(CPPDEFINES=["__MACPORTS__"]) # hack to fix libvpx MM256_BROADCASTSI128_SI256 define
else:
env["CC"] = "clang"
env["CXX"] = "clang++"
@@ -124,10 +122,9 @@ def configure(env):
env["AR"] = basecmd + "ar"
env["RANLIB"] = basecmd + "ranlib"
env["AS"] = basecmd + "as"
- env.Append(CPPDEFINES=["__MACPORTS__"]) # hack to fix libvpx MM256_BROADCASTSI128_SI256 define
if env["use_ubsan"] or env["use_asan"] or env["use_tsan"]:
- env.extra_suffix += "s"
+ env.extra_suffix += ".san"
if env["use_ubsan"]:
env.Append(
@@ -146,6 +143,10 @@ def configure(env):
env.Append(CCFLAGS=["-fsanitize=thread"])
env.Append(LINKFLAGS=["-fsanitize=thread"])
+ if env["use_coverage"]:
+ env.Append(CCFLAGS=["-ftest-coverage", "-fprofile-arcs"])
+ env.Append(LINKFLAGS=["-ftest-coverage", "-fprofile-arcs"])
+
## Dependencies
if env["builtin_libtheora"]:
@@ -182,10 +183,13 @@ def configure(env):
)
env.Append(LIBS=["pthread", "z"])
+ if env["opengl3"]:
+ env.Append(CPPDEFINES=["GLES_ENABLED", "GLES3_ENABLED"])
+ env.Append(CCFLAGS=["-Wno-deprecated-declarations"]) # Disable deprecation warnings
+ env.Append(LINKFLAGS=["-framework", "OpenGL"])
+
if env["vulkan"]:
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(CPPDEFINES=['GLES_ENABLED', 'OPENGL_ENABLED'])
diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h
index 06b14f1c14..3cc0b10c5b 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/osx/display_server_osx.h
@@ -36,9 +36,8 @@
#include "core/input/input.h"
#include "servers/display_server.h"
-#if defined(OPENGL_ENABLED)
-#include "context_gl_osx.h"
-//TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+#include "gl_manager_osx.h"
#endif
#if defined(VULKAN_ENABLED)
@@ -64,12 +63,12 @@ public:
NSMenu *_get_dock_menu() const;
void _menu_callback(id p_sender);
-#if defined(OPENGL_ENABLED)
- ContextGL_OSX *context_gles2;
+#if defined(GLES3_ENABLED)
+ GLManager_OSX *gl_manager = nullptr;
#endif
#if defined(VULKAN_ENABLED)
- VulkanContextOSX *context_vulkan;
- RenderingDeviceVulkan *rendering_device_vulkan;
+ VulkanContextOSX *context_vulkan = nullptr;
+ RenderingDeviceVulkan *rendering_device_vulkan = nullptr;
#endif
const NSMenu *_get_menu_root(const String &p_menu_root) const;
@@ -85,8 +84,8 @@ public:
bool pressed = false;
bool echo = false;
bool raw = false;
- Key keycode = KEY_NONE;
- uint32_t physical_keycode = 0;
+ Key keycode = Key::NONE;
+ Key physical_keycode = Key::NONE;
uint32_t unicode = 0;
};
@@ -109,9 +108,6 @@ public:
Vector<Vector2> mpath;
-#if defined(OPENGL_ENABLED)
- ContextGL_OSX *context_gles2 = nullptr;
-#endif
Point2i mouse_pos;
Size2i min_size;
@@ -176,7 +172,7 @@ public:
MouseMode mouse_mode;
Point2i last_mouse_pos;
- MouseButton last_button_state = MOUSE_BUTTON_NONE;
+ MouseButton last_button_state = MouseButton::NONE;
bool window_focused;
bool drop_events;
@@ -287,6 +283,7 @@ public:
virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override;
virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void gl_window_make_current(DisplayServer::WindowID p_window_id) override;
virtual void window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window = MAIN_WINDOW_ID) override;
virtual DisplayServer::VSyncMode window_get_vsync_mode(WindowID p_vsync_mode) const override;
@@ -305,6 +302,7 @@ public:
virtual void keyboard_set_current_layout(int p_index) override;
virtual String keyboard_get_layout_language(int p_index) const override;
virtual String keyboard_get_layout_name(int p_index) const override;
+ virtual Key keyboard_get_keycode_from_physical(Key p_keycode) const override;
virtual void process_events() override;
virtual void force_process_and_drop_events() override;
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 43b7d7c1e0..fec5c98a99 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -45,8 +45,8 @@
#include <IOKit/hid/IOHIDKeys.h>
#include <IOKit/hid/IOHIDLib.h>
-#if defined(OPENGL_ENABLED)
-//TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+#include "drivers/gles3/rasterizer_gles3.h"
#import <AppKit/NSOpenGLView.h>
#endif
@@ -166,9 +166,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
[pwd.window_object makeKeyAndOrderFront:nil]; // Move focus back to main window if there is no parent or other windows left.
}
-#if defined(OPENGL_ENABLED)
- if (DS_OSX->rendering_driver == "opengl_es") {
- //TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+ if (DS_OSX->rendering_driver == "opengl3") {
+ DS_OSX->gl_manager->window_destroy(window_id);
}
#endif
#ifdef VULKAN_ENABLED
@@ -190,6 +190,8 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
[wd.window_object setContentMinSize:NSMakeSize(0, 0)];
[wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
+ // Force window resize event.
+ [self windowDidResize:notification];
}
- (void)windowDidExitFullScreen:(NSNotification *)notification {
@@ -217,6 +219,8 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
if (wd.on_top) {
[wd.window_object setLevel:NSFloatingWindowLevel];
}
+ // Force window resize event.
+ [self windowDidResize:notification];
}
- (void)windowDidChangeBackingProperties:(NSNotification *)notification {
@@ -267,9 +271,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
layer.contentsScale = scale;
}
-#if defined(OPENGL_ENABLED)
- if (DS_OSX->rendering_driver == "opengl_es") {
- //TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+ if (DS_OSX->rendering_driver == "opengl3") {
+ DS_OSX->gl_manager->window_resize(window_id, wd.size.width, wd.size.height);
}
#endif
#if defined(VULKAN_ENABLED)
@@ -285,14 +289,6 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
Callable::CallError ce;
wd.rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce);
}
-
- if (OS_OSX::get_singleton()->get_main_loop()) {
- Main::force_redraw();
- //Event retrieval blocks until resize is over. Call Main::iteration() directly.
- if (!Main::is_iterating()) { //avoid cyclic loop
- Main::iteration();
- }
- }
}
- (void)windowDidMove:(NSNotification *)notification {
@@ -373,7 +369,12 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
/* GodotContentView */
/*************************************************************************/
+#if defined(GLES3_ENABLED)
+@interface GodotContentView : NSOpenGLView <NSTextInputClient> {
+#else
@interface GodotContentView : NSView <NSTextInputClient> {
+#endif
+
DisplayServerOSX::WindowID window_id;
NSTrackingArea *trackingArea;
NSMutableAttributedString *markedText;
@@ -401,12 +402,6 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (CALayer *)makeBackingLayer {
-#if defined(OPENGL_ENABLED)
- if (DS_OSX->rendering_driver == "opengl_es") {
- CALayer *layer = [[NSOpenGLLayer class] layer];
- return layer;
- }
-#endif
#if defined(VULKAN_ENABLED)
if (DS_OSX->rendering_driver == "vulkan") {
CALayer *layer = [[CAMetalLayer class] layer];
@@ -417,10 +412,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)updateLayer {
-#if defined(OPENGL_ENABLED)
- if (DS_OSX->rendering_driver == "opengl_es") {
- [super updateLayer];
- //TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+ if (DS_OSX->rendering_driver == "opengl3") {
+ DS_OSX->gl_manager->window_update(window_id);
}
#endif
#if defined(VULKAN_ENABLED)
@@ -585,8 +579,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
ke.pressed = true;
ke.echo = false;
ke.raw = false; // IME input event
- ke.keycode = KEY_NONE;
- ke.physical_keycode = 0;
+ ke.keycode = Key::NONE;
+ ke.physical_keycode = Key::NONE;
ke.unicode = codepoint;
_push_to_key_event_buffer(ke);
@@ -686,7 +680,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M
mb->set_position(pos);
mb->set_global_position(pos);
mb->set_button_mask(DS_OSX->last_button_state);
- if (index == MOUSE_BUTTON_LEFT && pressed) {
+ if (index == MouseButton::LEFT && pressed) {
mb->set_double_click([event clickCount] == 2);
}
@@ -699,10 +693,10 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M
if (([event modifierFlags] & NSEventModifierFlagControl)) {
wd.mouse_down_control = true;
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, true);
+ _mouseDownEvent(window_id, event, MouseButton::RIGHT, MouseButton::MASK_RIGHT, true);
} else {
wd.mouse_down_control = false;
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT, true);
+ _mouseDownEvent(window_id, event, MouseButton::LEFT, MouseButton::MASK_LEFT, true);
}
}
@@ -715,9 +709,9 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
if (wd.mouse_down_control) {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, false);
+ _mouseDownEvent(window_id, event, MouseButton::RIGHT, MouseButton::MASK_RIGHT, false);
} else {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_LEFT, MOUSE_BUTTON_MASK_LEFT, false);
+ _mouseDownEvent(window_id, event, MouseButton::LEFT, MouseButton::MASK_LEFT, false);
}
}
@@ -803,7 +797,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M
}
- (void)rightMouseDown:(NSEvent *)event {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, true);
+ _mouseDownEvent(window_id, event, MouseButton::RIGHT, MouseButton::MASK_RIGHT, true);
}
- (void)rightMouseDragged:(NSEvent *)event {
@@ -811,16 +805,16 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M
}
- (void)rightMouseUp:(NSEvent *)event {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_RIGHT, MOUSE_BUTTON_MASK_RIGHT, false);
+ _mouseDownEvent(window_id, event, MouseButton::RIGHT, MouseButton::MASK_RIGHT, false);
}
- (void)otherMouseDown:(NSEvent *)event {
if ((int)[event buttonNumber] == 2) {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_MASK_MIDDLE, true);
+ _mouseDownEvent(window_id, event, MouseButton::MIDDLE, MouseButton::MASK_MIDDLE, true);
} else if ((int)[event buttonNumber] == 3) {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_MASK_XBUTTON1, true);
+ _mouseDownEvent(window_id, event, MouseButton::MB_XBUTTON1, MouseButton::MASK_XBUTTON1, true);
} else if ((int)[event buttonNumber] == 4) {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON2, MOUSE_BUTTON_MASK_XBUTTON2, true);
+ _mouseDownEvent(window_id, event, MouseButton::MB_XBUTTON2, MouseButton::MASK_XBUTTON2, true);
} else {
return;
}
@@ -832,11 +826,11 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, M
- (void)otherMouseUp:(NSEvent *)event {
if ((int)[event buttonNumber] == 2) {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_MIDDLE, MOUSE_BUTTON_MASK_MIDDLE, false);
+ _mouseDownEvent(window_id, event, MouseButton::MIDDLE, MouseButton::MASK_MIDDLE, false);
} else if ((int)[event buttonNumber] == 3) {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON1, MOUSE_BUTTON_MASK_XBUTTON1, false);
+ _mouseDownEvent(window_id, event, MouseButton::MB_XBUTTON1, MouseButton::MASK_XBUTTON1, false);
} else if ((int)[event buttonNumber] == 4) {
- _mouseDownEvent(window_id, event, MOUSE_BUTTON_XBUTTON2, MOUSE_BUTTON_MASK_XBUTTON2, false);
+ _mouseDownEvent(window_id, event, MouseButton::MB_XBUTTON2, MouseButton::MASK_XBUTTON2, false);
} else {
return;
}
@@ -926,146 +920,155 @@ static bool isNumpadKey(unsigned int key) {
return false;
}
+// Keyboard symbol translation table
+static const Key _osx_to_godot_table[128] = {
+ /* 00 */ Key::A,
+ /* 01 */ Key::S,
+ /* 02 */ Key::D,
+ /* 03 */ Key::F,
+ /* 04 */ Key::H,
+ /* 05 */ Key::G,
+ /* 06 */ Key::Z,
+ /* 07 */ Key::X,
+ /* 08 */ Key::C,
+ /* 09 */ Key::V,
+ /* 0a */ Key::SECTION, /* ISO Section */
+ /* 0b */ Key::B,
+ /* 0c */ Key::Q,
+ /* 0d */ Key::W,
+ /* 0e */ Key::E,
+ /* 0f */ Key::R,
+ /* 10 */ Key::Y,
+ /* 11 */ Key::T,
+ /* 12 */ Key::KEY_1,
+ /* 13 */ Key::KEY_2,
+ /* 14 */ Key::KEY_3,
+ /* 15 */ Key::KEY_4,
+ /* 16 */ Key::KEY_6,
+ /* 17 */ Key::KEY_5,
+ /* 18 */ Key::EQUAL,
+ /* 19 */ Key::KEY_9,
+ /* 1a */ Key::KEY_7,
+ /* 1b */ Key::MINUS,
+ /* 1c */ Key::KEY_8,
+ /* 1d */ Key::KEY_0,
+ /* 1e */ Key::BRACERIGHT,
+ /* 1f */ Key::O,
+ /* 20 */ Key::U,
+ /* 21 */ Key::BRACELEFT,
+ /* 22 */ Key::I,
+ /* 23 */ Key::P,
+ /* 24 */ Key::ENTER,
+ /* 25 */ Key::L,
+ /* 26 */ Key::J,
+ /* 27 */ Key::APOSTROPHE,
+ /* 28 */ Key::K,
+ /* 29 */ Key::SEMICOLON,
+ /* 2a */ Key::BACKSLASH,
+ /* 2b */ Key::COMMA,
+ /* 2c */ Key::SLASH,
+ /* 2d */ Key::N,
+ /* 2e */ Key::M,
+ /* 2f */ Key::PERIOD,
+ /* 30 */ Key::TAB,
+ /* 31 */ Key::SPACE,
+ /* 32 */ Key::QUOTELEFT,
+ /* 33 */ Key::BACKSPACE,
+ /* 34 */ Key::UNKNOWN,
+ /* 35 */ Key::ESCAPE,
+ /* 36 */ Key::META,
+ /* 37 */ Key::META,
+ /* 38 */ Key::SHIFT,
+ /* 39 */ Key::CAPSLOCK,
+ /* 3a */ Key::ALT,
+ /* 3b */ Key::CTRL,
+ /* 3c */ Key::SHIFT,
+ /* 3d */ Key::ALT,
+ /* 3e */ Key::CTRL,
+ /* 3f */ Key::UNKNOWN, /* Function */
+ /* 40 */ Key::UNKNOWN, /* F17 */
+ /* 41 */ Key::KP_PERIOD,
+ /* 42 */ Key::UNKNOWN,
+ /* 43 */ Key::KP_MULTIPLY,
+ /* 44 */ Key::UNKNOWN,
+ /* 45 */ Key::KP_ADD,
+ /* 46 */ Key::UNKNOWN,
+ /* 47 */ Key::NUMLOCK, /* Really KeypadClear... */
+ /* 48 */ Key::VOLUMEUP, /* VolumeUp */
+ /* 49 */ Key::VOLUMEDOWN, /* VolumeDown */
+ /* 4a */ Key::VOLUMEMUTE, /* Mute */
+ /* 4b */ Key::KP_DIVIDE,
+ /* 4c */ Key::KP_ENTER,
+ /* 4d */ Key::UNKNOWN,
+ /* 4e */ Key::KP_SUBTRACT,
+ /* 4f */ Key::UNKNOWN, /* F18 */
+ /* 50 */ Key::UNKNOWN, /* F19 */
+ /* 51 */ Key::EQUAL, /* KeypadEqual */
+ /* 52 */ Key::KP_0,
+ /* 53 */ Key::KP_1,
+ /* 54 */ Key::KP_2,
+ /* 55 */ Key::KP_3,
+ /* 56 */ Key::KP_4,
+ /* 57 */ Key::KP_5,
+ /* 58 */ Key::KP_6,
+ /* 59 */ Key::KP_7,
+ /* 5a */ Key::UNKNOWN, /* F20 */
+ /* 5b */ Key::KP_8,
+ /* 5c */ Key::KP_9,
+ /* 5d */ Key::YEN, /* JIS Yen */
+ /* 5e */ Key::UNDERSCORE, /* JIS Underscore */
+ /* 5f */ Key::COMMA, /* JIS KeypadComma */
+ /* 60 */ Key::F5,
+ /* 61 */ Key::F6,
+ /* 62 */ Key::F7,
+ /* 63 */ Key::F3,
+ /* 64 */ Key::F8,
+ /* 65 */ Key::F9,
+ /* 66 */ Key::UNKNOWN, /* JIS Eisu */
+ /* 67 */ Key::F11,
+ /* 68 */ Key::UNKNOWN, /* JIS Kana */
+ /* 69 */ Key::F13,
+ /* 6a */ Key::F16,
+ /* 6b */ Key::F14,
+ /* 6c */ Key::UNKNOWN,
+ /* 6d */ Key::F10,
+ /* 6e */ Key::MENU,
+ /* 6f */ Key::F12,
+ /* 70 */ Key::UNKNOWN,
+ /* 71 */ Key::F15,
+ /* 72 */ Key::INSERT, /* Really Help... */
+ /* 73 */ Key::HOME,
+ /* 74 */ Key::PAGEUP,
+ /* 75 */ Key::KEY_DELETE,
+ /* 76 */ Key::F4,
+ /* 77 */ Key::END,
+ /* 78 */ Key::F2,
+ /* 79 */ Key::PAGEDOWN,
+ /* 7a */ Key::F1,
+ /* 7b */ Key::LEFT,
+ /* 7c */ Key::RIGHT,
+ /* 7d */ Key::DOWN,
+ /* 7e */ Key::UP,
+ /* 7f */ Key::UNKNOWN,
+};
+
// Translates a OS X keycode to a Godot keycode
-//
static Key translateKey(unsigned int key) {
- // Keyboard symbol translation table
- static const Key table[128] = {
- /* 00 */ KEY_A,
- /* 01 */ KEY_S,
- /* 02 */ KEY_D,
- /* 03 */ KEY_F,
- /* 04 */ KEY_H,
- /* 05 */ KEY_G,
- /* 06 */ KEY_Z,
- /* 07 */ KEY_X,
- /* 08 */ KEY_C,
- /* 09 */ KEY_V,
- /* 0a */ KEY_SECTION, /* ISO Section */
- /* 0b */ KEY_B,
- /* 0c */ KEY_Q,
- /* 0d */ KEY_W,
- /* 0e */ KEY_E,
- /* 0f */ KEY_R,
- /* 10 */ KEY_Y,
- /* 11 */ KEY_T,
- /* 12 */ KEY_1,
- /* 13 */ KEY_2,
- /* 14 */ KEY_3,
- /* 15 */ KEY_4,
- /* 16 */ KEY_6,
- /* 17 */ KEY_5,
- /* 18 */ KEY_EQUAL,
- /* 19 */ KEY_9,
- /* 1a */ KEY_7,
- /* 1b */ KEY_MINUS,
- /* 1c */ KEY_8,
- /* 1d */ KEY_0,
- /* 1e */ KEY_BRACERIGHT,
- /* 1f */ KEY_O,
- /* 20 */ KEY_U,
- /* 21 */ KEY_BRACELEFT,
- /* 22 */ KEY_I,
- /* 23 */ KEY_P,
- /* 24 */ KEY_ENTER,
- /* 25 */ KEY_L,
- /* 26 */ KEY_J,
- /* 27 */ KEY_APOSTROPHE,
- /* 28 */ KEY_K,
- /* 29 */ KEY_SEMICOLON,
- /* 2a */ KEY_BACKSLASH,
- /* 2b */ KEY_COMMA,
- /* 2c */ KEY_SLASH,
- /* 2d */ KEY_N,
- /* 2e */ KEY_M,
- /* 2f */ KEY_PERIOD,
- /* 30 */ KEY_TAB,
- /* 31 */ KEY_SPACE,
- /* 32 */ KEY_QUOTELEFT,
- /* 33 */ KEY_BACKSPACE,
- /* 34 */ KEY_UNKNOWN,
- /* 35 */ KEY_ESCAPE,
- /* 36 */ KEY_META,
- /* 37 */ KEY_META,
- /* 38 */ KEY_SHIFT,
- /* 39 */ KEY_CAPSLOCK,
- /* 3a */ KEY_ALT,
- /* 3b */ KEY_CTRL,
- /* 3c */ KEY_SHIFT,
- /* 3d */ KEY_ALT,
- /* 3e */ KEY_CTRL,
- /* 3f */ KEY_UNKNOWN, /* Function */
- /* 40 */ KEY_UNKNOWN, /* F17 */
- /* 41 */ KEY_KP_PERIOD,
- /* 42 */ KEY_UNKNOWN,
- /* 43 */ KEY_KP_MULTIPLY,
- /* 44 */ KEY_UNKNOWN,
- /* 45 */ KEY_KP_ADD,
- /* 46 */ KEY_UNKNOWN,
- /* 47 */ KEY_NUMLOCK, /* Really KeypadClear... */
- /* 48 */ KEY_VOLUMEUP, /* VolumeUp */
- /* 49 */ KEY_VOLUMEDOWN, /* VolumeDown */
- /* 4a */ KEY_VOLUMEMUTE, /* Mute */
- /* 4b */ KEY_KP_DIVIDE,
- /* 4c */ KEY_KP_ENTER,
- /* 4d */ KEY_UNKNOWN,
- /* 4e */ KEY_KP_SUBTRACT,
- /* 4f */ KEY_UNKNOWN, /* F18 */
- /* 50 */ KEY_UNKNOWN, /* F19 */
- /* 51 */ KEY_EQUAL, /* KeypadEqual */
- /* 52 */ KEY_KP_0,
- /* 53 */ KEY_KP_1,
- /* 54 */ KEY_KP_2,
- /* 55 */ KEY_KP_3,
- /* 56 */ KEY_KP_4,
- /* 57 */ KEY_KP_5,
- /* 58 */ KEY_KP_6,
- /* 59 */ KEY_KP_7,
- /* 5a */ KEY_UNKNOWN, /* F20 */
- /* 5b */ KEY_KP_8,
- /* 5c */ KEY_KP_9,
- /* 5d */ KEY_YEN, /* JIS Yen */
- /* 5e */ KEY_UNDERSCORE, /* JIS Underscore */
- /* 5f */ KEY_COMMA, /* JIS KeypadComma */
- /* 60 */ KEY_F5,
- /* 61 */ KEY_F6,
- /* 62 */ KEY_F7,
- /* 63 */ KEY_F3,
- /* 64 */ KEY_F8,
- /* 65 */ KEY_F9,
- /* 66 */ KEY_UNKNOWN, /* JIS Eisu */
- /* 67 */ KEY_F11,
- /* 68 */ KEY_UNKNOWN, /* JIS Kana */
- /* 69 */ KEY_F13,
- /* 6a */ KEY_F16,
- /* 6b */ KEY_F14,
- /* 6c */ KEY_UNKNOWN,
- /* 6d */ KEY_F10,
- /* 6e */ KEY_MENU,
- /* 6f */ KEY_F12,
- /* 70 */ KEY_UNKNOWN,
- /* 71 */ KEY_F15,
- /* 72 */ KEY_INSERT, /* Really Help... */
- /* 73 */ KEY_HOME,
- /* 74 */ KEY_PAGEUP,
- /* 75 */ KEY_DELETE,
- /* 76 */ KEY_F4,
- /* 77 */ KEY_END,
- /* 78 */ KEY_F2,
- /* 79 */ KEY_PAGEDOWN,
- /* 7a */ KEY_F1,
- /* 7b */ KEY_LEFT,
- /* 7c */ KEY_RIGHT,
- /* 7d */ KEY_DOWN,
- /* 7e */ KEY_UP,
- /* 7f */ KEY_UNKNOWN,
- };
-
if (key >= 128) {
- return KEY_UNKNOWN;
+ return Key::UNKNOWN;
}
- return table[key];
+ return _osx_to_godot_table[key];
+}
+
+// Translates a Godot keycode back to a OSX keycode
+static unsigned int unmapKey(Key key) {
+ for (int i = 0; i <= 126; i++) {
+ if (_osx_to_godot_table[i] == key) {
+ return i;
+ }
+ }
+ return 127;
}
struct _KeyCodeMap {
@@ -1074,61 +1077,61 @@ struct _KeyCodeMap {
};
static const _KeyCodeMap _keycodes[55] = {
- { '`', KEY_QUOTELEFT },
- { '~', KEY_ASCIITILDE },
- { '0', KEY_0 },
- { '1', KEY_1 },
- { '2', KEY_2 },
- { '3', KEY_3 },
- { '4', KEY_4 },
- { '5', KEY_5 },
- { '6', KEY_6 },
- { '7', KEY_7 },
- { '8', KEY_8 },
- { '9', KEY_9 },
- { '-', KEY_MINUS },
- { '_', KEY_UNDERSCORE },
- { '=', KEY_EQUAL },
- { '+', KEY_PLUS },
- { 'q', KEY_Q },
- { 'w', KEY_W },
- { 'e', KEY_E },
- { 'r', KEY_R },
- { 't', KEY_T },
- { 'y', KEY_Y },
- { 'u', KEY_U },
- { 'i', KEY_I },
- { 'o', KEY_O },
- { 'p', KEY_P },
- { '[', KEY_BRACELEFT },
- { ']', KEY_BRACERIGHT },
- { '{', KEY_BRACELEFT },
- { '}', KEY_BRACERIGHT },
- { 'a', KEY_A },
- { 's', KEY_S },
- { 'd', KEY_D },
- { 'f', KEY_F },
- { 'g', KEY_G },
- { 'h', KEY_H },
- { 'j', KEY_J },
- { 'k', KEY_K },
- { 'l', KEY_L },
- { ';', KEY_SEMICOLON },
- { ':', KEY_COLON },
- { '\'', KEY_APOSTROPHE },
- { '\"', KEY_QUOTEDBL },
- { '\\', KEY_BACKSLASH },
- { '#', KEY_NUMBERSIGN },
- { 'z', KEY_Z },
- { 'x', KEY_X },
- { 'c', KEY_C },
- { 'v', KEY_V },
- { 'b', KEY_B },
- { 'n', KEY_N },
- { 'm', KEY_M },
- { ',', KEY_COMMA },
- { '.', KEY_PERIOD },
- { '/', KEY_SLASH }
+ { '`', Key::QUOTELEFT },
+ { '~', Key::ASCIITILDE },
+ { '0', Key::KEY_0 },
+ { '1', Key::KEY_1 },
+ { '2', Key::KEY_2 },
+ { '3', Key::KEY_3 },
+ { '4', Key::KEY_4 },
+ { '5', Key::KEY_5 },
+ { '6', Key::KEY_6 },
+ { '7', Key::KEY_7 },
+ { '8', Key::KEY_8 },
+ { '9', Key::KEY_9 },
+ { '-', Key::MINUS },
+ { '_', Key::UNDERSCORE },
+ { '=', Key::EQUAL },
+ { '+', Key::PLUS },
+ { 'q', Key::Q },
+ { 'w', Key::W },
+ { 'e', Key::E },
+ { 'r', Key::R },
+ { 't', Key::T },
+ { 'y', Key::Y },
+ { 'u', Key::U },
+ { 'i', Key::I },
+ { 'o', Key::O },
+ { 'p', Key::P },
+ { '[', Key::BRACELEFT },
+ { ']', Key::BRACERIGHT },
+ { '{', Key::BRACELEFT },
+ { '}', Key::BRACERIGHT },
+ { 'a', Key::A },
+ { 's', Key::S },
+ { 'd', Key::D },
+ { 'f', Key::F },
+ { 'g', Key::G },
+ { 'h', Key::H },
+ { 'j', Key::J },
+ { 'k', Key::K },
+ { 'l', Key::L },
+ { ';', Key::SEMICOLON },
+ { ':', Key::COLON },
+ { '\'', Key::APOSTROPHE },
+ { '\"', Key::QUOTEDBL },
+ { '\\', Key::BACKSLASH },
+ { '#', Key::NUMBERSIGN },
+ { 'z', Key::Z },
+ { 'x', Key::X },
+ { 'c', Key::C },
+ { 'v', Key::V },
+ { 'b', Key::B },
+ { 'n', Key::N },
+ { 'm', Key::M },
+ { ',', Key::COMMA },
+ { '.', Key::PERIOD },
+ { '/', Key::SLASH }
};
static Key remapKey(unsigned int key, unsigned int state) {
@@ -1342,7 +1345,7 @@ inline void sendScrollEvent(DisplayServer::WindowID window_id, MouseButton butto
ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
- MouseButton mask = MouseButton(1 << (button - 1));
+ MouseButton mask = mouse_button_to_mask(button);
Ref<InputEventMouseButton> sc;
sc.instantiate();
@@ -1415,10 +1418,10 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy
sendPanEvent(window_id, deltaX, deltaY, [event modifierFlags]);
} else {
if (fabs(deltaX)) {
- sendScrollEvent(window_id, 0 > deltaX ? MOUSE_BUTTON_WHEEL_RIGHT : MOUSE_BUTTON_WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]);
+ sendScrollEvent(window_id, 0 > deltaX ? MouseButton::WHEEL_RIGHT : MouseButton::WHEEL_LEFT, fabs(deltaX * 0.3), [event modifierFlags]);
}
if (fabs(deltaY)) {
- sendScrollEvent(window_id, 0 < deltaY ? MOUSE_BUTTON_WHEEL_UP : MOUSE_BUTTON_WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]);
+ sendScrollEvent(window_id, 0 < deltaY ? MouseButton::WHEEL_UP : MouseButton::WHEEL_DOWN, fabs(deltaY * 0.3), [event modifierFlags]);
}
}
}
@@ -1917,6 +1920,7 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
return;
}
+ WindowData &wd = windows[MAIN_WINDOW_ID];
if (p_mode == MOUSE_MODE_CAPTURED) {
// Apple Docs state that the display parameter is not used.
// "This parameter is not used. By default, you may pass kCGDirectMainDisplay."
@@ -1925,7 +1929,7 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
CGDisplayHideCursor(kCGDirectMainDisplay);
}
CGAssociateMouseAndMouseCursorPosition(false);
- WindowData &wd = windows[MAIN_WINDOW_ID];
+ [wd.window_object setMovable:NO];
const NSRect contentRect = [wd.window_view frame];
NSRect pointInWindowRect = NSMakeRect(contentRect.size.width / 2, contentRect.size.height / 2, 0, 0);
NSPoint pointOnScreen = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin;
@@ -1935,17 +1939,21 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
CGDisplayHideCursor(kCGDirectMainDisplay);
}
+ [wd.window_object setMovable:YES];
CGAssociateMouseAndMouseCursorPosition(true);
} else if (p_mode == MOUSE_MODE_CONFINED) {
CGDisplayShowCursor(kCGDirectMainDisplay);
+ [wd.window_object setMovable:NO];
CGAssociateMouseAndMouseCursorPosition(false);
} else if (p_mode == MOUSE_MODE_CONFINED_HIDDEN) {
if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
CGDisplayHideCursor(kCGDirectMainDisplay);
}
+ [wd.window_object setMovable:NO];
CGAssociateMouseAndMouseCursorPosition(false);
} else { // MOUSE_MODE_VISIBLE
CGDisplayShowCursor(kCGDirectMainDisplay);
+ [wd.window_object setMovable:YES];
CGAssociateMouseAndMouseCursorPosition(true);
}
@@ -2573,8 +2581,8 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
//TODO - implement transparency for Vulkan
}
#endif
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
//TODO - reimplement OpenGLES
}
#endif
@@ -2592,15 +2600,15 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
//TODO - implement transparency for Vulkan
}
#endif
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
//TODO - reimplement OpenGLES
}
#endif
wd.layered_window = false;
}
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
//TODO - reimplement OpenGLES
}
#endif
@@ -3001,7 +3009,7 @@ void DisplayServerOSX::cursor_set_custom_image(const RES &p_cursor, CursorShape
ERR_FAIL_COND(!image.is_valid());
NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
- initWithBitmapDataPlanes:NULL
+ initWithBitmapDataPlanes:nullptr
pixelsWide:int(texture_size.width)
pixelsHigh:int(texture_size.height)
bitsPerSample:8
@@ -3196,6 +3204,17 @@ String DisplayServerOSX::keyboard_get_layout_name(int p_index) const {
return kbd_layouts[p_index].name;
}
+Key DisplayServerOSX::keyboard_get_keycode_from_physical(Key p_keycode) const {
+ if (p_keycode == Key::PAUSE) {
+ return p_keycode;
+ }
+
+ Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK;
+ Key keycode_no_mod = p_keycode & KeyModifierMask::CODE_MASK;
+ unsigned int osx_keycode = unmapKey((Key)keycode_no_mod);
+ return (Key)(remapKey(osx_keycode, 0) | modifiers);
+}
+
void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) {
Ref<InputEvent> ev = p_event;
Input::get_singleton()->parse_input_event(ev);
@@ -3249,8 +3268,8 @@ void DisplayServerOSX::_send_event(NSEvent *p_event) {
_get_key_modifier_state([p_event modifierFlags], k);
k->set_window_id(DisplayServerOSX::INVALID_WINDOW_ID);
k->set_pressed(true);
- k->set_keycode(KEY_PERIOD);
- k->set_physical_keycode(KEY_PERIOD);
+ k->set_keycode(Key::PERIOD);
+ k->set_physical_keycode(Key::PERIOD);
k->set_echo([p_event isARepeat]);
Input::get_singleton()->parse_input_event(k);
@@ -3277,20 +3296,20 @@ void DisplayServerOSX::_process_key_events() {
_push_input(k);
} else {
// IME input
- if ((i == 0 && ke.keycode == 0) || (i > 0 && key_event_buffer[i - 1].keycode == 0)) {
+ if ((i == 0 && ke.keycode == Key::NONE) || (i > 0 && key_event_buffer[i - 1].keycode == Key::NONE)) {
k.instantiate();
k->set_window_id(ke.window_id);
_get_key_modifier_state(ke.osx_state, k);
k->set_pressed(ke.pressed);
k->set_echo(ke.echo);
- k->set_keycode(KEY_NONE);
- k->set_physical_keycode(KEY_NONE);
+ k->set_keycode(Key::NONE);
+ k->set_physical_keycode(Key::NONE);
k->set_unicode(ke.unicode);
_push_input(k);
}
- if (ke.keycode != 0) {
+ if (ke.keycode != Key::NONE) {
k.instantiate();
k->set_window_id(ke.window_id);
@@ -3300,7 +3319,7 @@ void DisplayServerOSX::_process_key_events() {
k->set_keycode(ke.keycode);
k->set_physical_keycode((Key)ke.physical_keycode);
- if (i + 1 < key_event_pos && key_event_buffer[i + 1].keycode == 0) {
+ if (i + 1 < key_event_pos && key_event_buffer[i + 1].keycode == Key::NONE) {
k->set_unicode(key_event_buffer[i + 1].unicode);
}
@@ -3394,7 +3413,7 @@ void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) {
img = img->duplicate();
img->convert(Image::FORMAT_RGBA8);
NSBitmapImageRep *imgrep = [[NSBitmapImageRep alloc]
- initWithBitmapDataPlanes:NULL
+ initWithBitmapDataPlanes:nullptr
pixelsWide:img->get_width()
pixelsHigh:img->get_height()
bitsPerSample:8
@@ -3431,18 +3450,31 @@ void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) {
void DisplayServerOSX::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
_THREAD_SAFE_METHOD_
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
+ gl_manager->swap_buffers();
+ }
+#endif
#if defined(VULKAN_ENABLED)
- context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+ if (rendering_driver == "vulkan") {
+ context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+ }
#endif
}
DisplayServer::VSyncMode DisplayServerOSX::window_get_vsync_mode(WindowID p_window) const {
_THREAD_SAFE_METHOD_
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
+ return (gl_manager->is_using_vsync() ? DisplayServer::VSyncMode::VSYNC_ENABLED : DisplayServer::VSyncMode::VSYNC_DISABLED);
+ }
+#endif
#if defined(VULKAN_ENABLED)
- return context_vulkan->get_vsync_mode(p_window);
-#else
- return DisplayServer::VSYNC_ENABLED;
+ if (rendering_driver == "vulkan") {
+ return context_vulkan->get_vsync_mode(p_window);
+ }
#endif
+ return DisplayServer::VSYNC_ENABLED;
}
Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
@@ -3451,13 +3483,19 @@ Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
#if defined(VULKAN_ENABLED)
drivers.push_back("vulkan");
#endif
-#if defined(OPENGL_ENABLED)
- drivers.push_back("opengl_es");
+#if defined(GLES3_ENABLED)
+ drivers.push_back("opengl3");
#endif
return drivers;
}
+void DisplayServerOSX::gl_window_make_current(DisplayServer::WindowID p_window_id) {
+#if defined(GLES3_ENABLED)
+ gl_manager->window_make_current(p_window_id);
+#endif
+}
+
Point2i DisplayServerOSX::ime_get_selection() const {
return im_selection;
}
@@ -3498,7 +3536,7 @@ ObjectID DisplayServerOSX::window_get_attached_instance_id(WindowID p_window) co
DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error));
if (r_error != OK) {
- OS::get_singleton()->alert("Your video card driver does not support any of the supported Metal versions.", "Unable to initialize Video driver");
+ OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan or OpenGL versions.", "Unable to initialize Video driver");
}
return ds;
}
@@ -3555,9 +3593,12 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, V
}
}
#endif
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
- //TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
+ if (gl_manager) {
+ Error err = gl_manager->window_create(window_id_counter, wd.window_view, p_rect.size.width, p_rect.size.height);
+ ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL context");
+ }
}
#endif
id = window_id_counter++;
@@ -3576,9 +3617,9 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, V
layer.contentsScale = scale;
}
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
- //TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
+ gl_manager->window_resize(id, wd.size.width, wd.size.height);
}
#endif
#if defined(VULKAN_ENABLED)
@@ -3630,15 +3671,15 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) {
}
void DisplayServerOSX::release_rendering_thread() {
- //TODO - reimplement OpenGLES
}
void DisplayServerOSX::make_rendering_thread() {
- //TODO - reimplement OpenGLES
}
void DisplayServerOSX::swap_buffers() {
- //TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+ gl_manager->swap_buffers();
+#endif
}
void DisplayServerOSX::console_set_visible(bool p_enabled) {
@@ -3726,17 +3767,20 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
[main_menu setSubmenu:apple_menu forItem:menu_item];
//!!!!!!!!!!!!!!!!!!!!!!!!!!
- //TODO - do Vulkan and GLES2 support checks, driver selection and fallback
+ //TODO - do Vulkan and OpenGL support checks, driver selection and fallback
rendering_driver = p_rendering_driver;
-#ifndef _MSC_VER
-#warning Forcing vulkan rendering driver because OpenGL not implemented yet
-#endif
- rendering_driver = "vulkan";
-
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
- //TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
+ GLManager_OSX::ContextType opengl_api_type = GLManager_OSX::GLES_3_0_COMPATIBLE;
+ gl_manager = memnew(GLManager_OSX(opengl_api_type));
+ if (gl_manager->initialize() != OK) {
+ memdelete(gl_manager);
+ gl_manager = nullptr;
+ r_error = ERR_UNAVAILABLE;
+ ERR_FAIL_MSG("Could not initialize OpenGL");
+ return;
+ }
}
#endif
#if defined(VULKAN_ENABLED)
@@ -3763,9 +3807,9 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
}
show_window(MAIN_WINDOW_ID);
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
- //TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+ if (rendering_driver == "opengl3") {
+ RasterizerGLES3::make_current();
}
#endif
#if defined(VULKAN_ENABLED)
@@ -3796,21 +3840,22 @@ DisplayServerOSX::~DisplayServerOSX() {
}
//destroy drivers
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
- //TODO - reimplement OpenGLES
+#if defined(GLES3_ENABLED)
+ if (gl_manager) {
+ memdelete(gl_manager);
+ gl_manager = nullptr;
}
#endif
#if defined(VULKAN_ENABLED)
- if (rendering_driver == "vulkan") {
- if (rendering_device_vulkan) {
- rendering_device_vulkan->finalize();
- memdelete(rendering_device_vulkan);
- }
+ if (rendering_device_vulkan) {
+ rendering_device_vulkan->finalize();
+ memdelete(rendering_device_vulkan);
+ rendering_device_vulkan = nullptr;
+ }
- if (context_vulkan) {
- memdelete(context_vulkan);
- }
+ if (context_vulkan) {
+ memdelete(context_vulkan);
+ context_vulkan = nullptr;
}
#endif
diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp
index 54a3104482..8126510245 100644
--- a/platform/osx/export/export_plugin.cpp
+++ b/platform/osx/export/export_plugin.cpp
@@ -95,6 +95,7 @@ void EditorExportPlatformOSX::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_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::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()));
@@ -324,11 +325,11 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
}
/**
- If we're running the OSX version of the Godot editor we'll:
- - export our application bundle to a temporary folder
- - attempt to code sign it
- - and then wrap it up in a DMG
-**/
+ * If we're running the OSX version of the Godot editor we'll:
+ * - export our application bundle to a temporary folder
+ * - attempt to code sign it
+ * - and then wrap it up in a DMG
+ */
Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
#ifdef OSX_ENABLED
@@ -480,10 +481,10 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
src_pkg_name = p_preset->get("custom_template/release");
}
- if (src_pkg_name == "") {
+ if (src_pkg_name.is_empty()) {
String err;
src_pkg_name = find_export_template("osx.zip", &err);
- if (src_pkg_name == "") {
+ if (src_pkg_name.is_empty()) {
EditorNode::add_io_error(err);
return ERR_FILE_NOT_FOUND;
}
@@ -535,6 +536,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
err = ERR_CANT_CREATE;
}
+ Array helpers = p_preset->get("codesign/entitlements/app_sandbox/helper_executables");
+
// Create our folder structure.
if (err == OK) {
print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
@@ -546,6 +549,11 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
err = tmp_app_dir->make_dir_recursive(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) {
print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
@@ -553,7 +561,6 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
// Now process our template.
bool found_binary = false;
- int total_size = 0;
Vector<String> dylibs_found;
while (ret == UNZ_OK && err == OK) {
@@ -600,7 +607,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
iconpath = ProjectSettings::get_singleton()->get("application/config/icon");
}
- if (iconpath != "") {
+ if (!iconpath.is_empty()) {
if (iconpath.get_extension() == "icns") {
FileAccess *icon = FileAccess::open(iconpath, FileAccess::READ);
if (icon) {
@@ -641,7 +648,6 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
print_line("ADDING: " + file + " size: " + itos(data.size()));
- total_size += data.size();
// Write it into our application bundle.
file = tmp_app_path_name.plus_file(file);
@@ -688,7 +694,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
bool sign_enabled = p_preset->get("codesign/enable");
String ent_path = p_preset->get("codesign/entitlements/custom_file");
- if (sign_enabled && (ent_path == "")) {
+ String hlp_ent_path = EditorPaths::get_singleton()->get_cache_dir().plus_file(pkg_name + "_helper.entitlements");
+ if (sign_enabled && (ent_path.is_empty())) {
ent_path = EditorPaths::get_singleton()->get_cache_dir().plus_file(pkg_name + ".entitlements");
FileAccess *ent_f = FileAccess::open(ent_path, FileAccess::WRITE);
@@ -819,10 +826,43 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
} else {
err = ERR_CANT_CREATE;
}
+
+ if ((err == OK) && helpers.size() > 0) {
+ ent_f = FileAccess::open(hlp_ent_path, FileAccess::WRITE);
+ if (ent_f) {
+ ent_f->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ ent_f->store_line("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
+ ent_f->store_line("<plist version=\"1.0\">");
+ ent_f->store_line("<dict>");
+ ent_f->store_line("<key>com.apple.security.app-sandbox</key>");
+ ent_f->store_line("<true/>");
+ ent_f->store_line("<key>com.apple.security.inherit</key>");
+ ent_f->store_line("<true/>");
+ ent_f->store_line("</dict>");
+ ent_f->store_line("</plist>");
+
+ ent_f->close();
+ memdelete(ent_f);
+ } else {
+ err = ERR_CANT_CREATE;
+ }
+ }
+ }
+
+ if ((err == OK) && helpers.size() > 0) {
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ for (int i = 0; i < helpers.size(); i++) {
+ String hlp_path = helpers[i];
+ err = da->copy(hlp_path, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file());
+ if (err == OK && sign_enabled) {
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), hlp_ent_path);
+ }
+ FileAccess::set_unix_permissions(tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), 0755);
+ }
}
if (err == OK) {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
for (int i = 0; i < shared_objects.size(); i++) {
String src_path = ProjectSettings::get_singleton()->globalize_path(shared_objects[i].path);
if (da->dir_exists(src_path)) {
@@ -842,7 +882,6 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file(), ent_path);
}
}
- memdelete(da);
}
if (sign_enabled) {
@@ -903,6 +942,9 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
err = _notarize(p_preset, p_path);
}
+ // Clean up temporary entitlements files.
+ DirAccess::remove_file_or_error(hlp_ent_path);
+
// Clean up temporary .app dir.
tmp_app_dir->change_dir(tmp_app_path_name);
tmp_app_dir->erase_contents_recursive();
@@ -916,11 +958,12 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name) {
String dir = p_root_path.plus_file(p_folder);
- DirAccess *da = DirAccess::open(dir);
+ DirAccessRef da = DirAccess::open(dir);
da->list_dir_begin();
- String f;
- while ((f = da->get_next()) != "") {
+ String f = da->get_next();
+ while (!f.is_empty()) {
if (f == "." || f == "..") {
+ f = da->get_next();
continue;
}
if (da->is_link(f)) {
@@ -967,7 +1010,7 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
} else if (da->current_is_dir()) {
_zip_folder_recursive(p_zip, p_root_path, p_folder.plus_file(f), p_pkg_name);
} else {
- bool is_executable = (p_folder.ends_with("MacOS") && (f == p_pkg_name));
+ bool is_executable = (p_folder.ends_with("MacOS") && (f == p_pkg_name)) || p_folder.ends_with("Helpers");
OS::Time time = OS::get_singleton()->get_time();
OS::Date date = OS::get_singleton()->get_date();
@@ -1006,13 +1049,26 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
0x0314, // "version made by", 0x03 - Unix, 0x14 - ZIP specification version 2.0, required to store Unix file permissions
0);
- Vector<uint8_t> array = FileAccess::get_file_as_array(dir.plus_file(f));
- zipWriteInFileInZip(p_zip, array.ptr(), array.size());
+ FileAccessRef fa = FileAccess::open(dir.plus_file(f), FileAccess::READ);
+ if (!fa) {
+ ERR_FAIL_MSG("Can't open file to read from path '" + String(dir.plus_file(f)) + "'.");
+ }
+ const int bufsize = 16384;
+ uint8_t buf[bufsize];
+
+ while (true) {
+ uint64_t got = fa->get_buffer(buf, bufsize);
+ if (got == 0) {
+ break;
+ }
+ zipWriteInFileInZip(p_zip, buf, got);
+ }
+
zipCloseFileInZip(p_zip);
}
+ f = da->get_next();
}
da->list_dir_end();
- memdelete(da);
}
bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
diff --git a/platform/osx/export/export_plugin.h b/platform/osx/export/export_plugin.h
index cd85ce2aad..ca5086622e 100644
--- a/platform/osx/export/export_plugin.h
+++ b/platform/osx/export/export_plugin.h
@@ -115,7 +115,7 @@ public:
virtual void get_platform_features(List<String> *r_features) override {
r_features->push_back("pc");
r_features->push_back("s3tc");
- r_features->push_back("macOS");
+ r_features->push_back("macos");
}
virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override {
diff --git a/platform/osx/context_gl_osx.h b/platform/osx/gl_manager_osx.h
index ac45559217..f86bc805c1 100644
--- a/platform/osx/context_gl_osx.h
+++ b/platform/osx/gl_manager_osx.h
@@ -1,5 +1,5 @@
/*************************************************************************/
-/* context_gl_osx.h */
+/* gl_manager_osx.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
@@ -28,47 +28,79 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#ifndef CONTEXT_GL_OSX_H
-#define CONTEXT_GL_OSX_H
+#ifndef GL_MANAGER_OSX_H
+#define GL_MANAGER_OSX_H
-#if defined(OPENGL_ENABLED) || defined(GLES_ENABLED)
+#if defined(OSX_ENABLED) && defined(GLES3_ENABLED)
#include "core/error/error_list.h"
#include "core/os/os.h"
+#include "core/templates/local_vector.h"
+#include "servers/display_server.h"
#include <AppKit/AppKit.h>
#include <ApplicationServices/ApplicationServices.h>
#include <CoreVideo/CoreVideo.h>
-class ContextGL_OSX {
- bool opengl_3_context;
- bool use_vsync;
+class GLManager_OSX {
+public:
+ enum ContextType {
+ GLES_3_0_COMPATIBLE,
+ };
+
+private:
+ struct GLWindow {
+ GLWindow() { in_use = false; }
+ bool in_use;
+
+ DisplayServer::WindowID window_id;
+ int width;
+ int height;
+
+ id window_view;
+ NSOpenGLContext *context;
+ };
+
+ LocalVector<GLWindow> _windows;
+
+ NSOpenGLContext *_shared_context = nullptr;
+ GLWindow *_current_window;
+
+ Error _create_context(GLWindow &win);
+ void _internal_set_current_window(GLWindow *p_win);
- void *framework;
- id window_view;
- NSOpenGLPixelFormat *pixelFormat;
- NSOpenGLContext *context;
+ GLWindow &get_window(unsigned int id) { return _windows[id]; }
+ const GLWindow &get_window(unsigned int id) const { return _windows[id]; }
+
+ bool use_vsync;
+ ContextType context_type;
public:
- void release_current();
+ Error window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height);
+ void window_destroy(DisplayServer::WindowID p_window_id);
+ void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height);
+
+ // get directly from the cached GLWindow
+ int window_get_width(DisplayServer::WindowID p_window_id = 0);
+ int window_get_height(DisplayServer::WindowID p_window_id = 0);
+ void release_current();
void make_current();
- void update();
+ void swap_buffers();
- void set_opacity(GLint p_opacity);
+ void window_make_current(DisplayServer::WindowID p_window_id);
- int get_window_width();
- int get_window_height();
- void swap_buffers();
+ void window_update(DisplayServer::WindowID p_window_id);
Error initialize();
void set_use_vsync(bool p_use);
bool is_using_vsync() const;
- ContextGL_OSX(id p_view, bool p_opengl_3_context);
- ~ContextGL_OSX();
+ GLManager_OSX(ContextType p_context_type);
+ ~GLManager_OSX();
};
-#endif
-#endif
+#endif // defined(OSX_ENABLED) && defined(GLES3_ENABLED)
+
+#endif // GL_MANAGER_OSX_H
diff --git a/platform/osx/gl_manager_osx.mm b/platform/osx/gl_manager_osx.mm
new file mode 100644
index 0000000000..60e0706fc0
--- /dev/null
+++ b/platform/osx/gl_manager_osx.mm
@@ -0,0 +1,233 @@
+/*************************************************************************/
+/* gl_manager_osx.mm */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "gl_manager_osx.h"
+
+#ifdef OSX_ENABLED
+#ifdef GLES3_ENABLED
+
+#include <stdio.h>
+#include <stdlib.h>
+
+Error GLManager_OSX::_create_context(GLWindow &win) {
+ NSOpenGLPixelFormatAttribute attributes[] = {
+ NSOpenGLPFADoubleBuffer,
+ NSOpenGLPFAClosestPolicy,
+ NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core,
+ NSOpenGLPFAColorSize, 32,
+ NSOpenGLPFADepthSize, 24,
+ NSOpenGLPFAStencilSize, 8,
+ 0
+ };
+
+ NSOpenGLPixelFormat *pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
+ ERR_FAIL_COND_V(pixel_format == nil, ERR_CANT_CREATE);
+
+ win.context = [[NSOpenGLContext alloc] initWithFormat:pixel_format shareContext:_shared_context];
+ ERR_FAIL_COND_V(win.context == nil, ERR_CANT_CREATE);
+ if (_shared_context == nullptr) {
+ _shared_context = win.context;
+ }
+
+ [win.context setView:win.window_view];
+ [win.context makeCurrentContext];
+
+ return OK;
+}
+
+Error GLManager_OSX::window_create(DisplayServer::WindowID p_window_id, id p_view, int p_width, int p_height) {
+ if (p_window_id >= (int)_windows.size()) {
+ _windows.resize(p_window_id + 1);
+ }
+
+ GLWindow &win = _windows[p_window_id];
+ win.in_use = true;
+ win.window_id = p_window_id;
+ win.width = p_width;
+ win.height = p_height;
+ win.window_view = p_view;
+
+ if (_create_context(win) != OK) {
+ _windows.remove_at(_windows.size() - 1);
+ return FAILED;
+ }
+
+ window_make_current(_windows.size() - 1);
+
+ return OK;
+}
+
+void GLManager_OSX::_internal_set_current_window(GLWindow *p_win) {
+ _current_window = p_win;
+}
+
+void GLManager_OSX::window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {
+ if (p_window_id == -1) {
+ return;
+ }
+
+ GLWindow &win = _windows[p_window_id];
+ if (!win.in_use) {
+ return;
+ }
+
+ win.width = p_width;
+ win.height = p_height;
+
+ GLint dim[2];
+ dim[0] = p_width;
+ dim[1] = p_height;
+ CGLSetParameter((CGLContextObj)[win.context CGLContextObj], kCGLCPSurfaceBackingSize, &dim[0]);
+ CGLEnable((CGLContextObj)[win.context CGLContextObj], kCGLCESurfaceBackingSize);
+ if (OS::get_singleton()->is_hidpi_allowed()) {
+ [win.window_view setWantsBestResolutionOpenGLSurface:YES];
+ } else {
+ [win.window_view setWantsBestResolutionOpenGLSurface:NO];
+ }
+
+ [win.context update];
+}
+
+int GLManager_OSX::window_get_width(DisplayServer::WindowID p_window_id) {
+ return get_window(p_window_id).width;
+}
+
+int GLManager_OSX::window_get_height(DisplayServer::WindowID p_window_id) {
+ return get_window(p_window_id).height;
+}
+
+void GLManager_OSX::window_destroy(DisplayServer::WindowID p_window_id) {
+ GLWindow &win = get_window(p_window_id);
+ win.in_use = false;
+
+ if (_current_window == &win) {
+ _current_window = nullptr;
+ }
+}
+
+void GLManager_OSX::release_current() {
+ if (!_current_window) {
+ return;
+ }
+
+ [NSOpenGLContext clearCurrentContext];
+}
+
+void GLManager_OSX::window_make_current(DisplayServer::WindowID p_window_id) {
+ if (p_window_id == -1) {
+ return;
+ }
+
+ GLWindow &win = _windows[p_window_id];
+ if (!win.in_use) {
+ return;
+ }
+
+ if (&win == _current_window) {
+ return;
+ }
+
+ [win.context makeCurrentContext];
+
+ _internal_set_current_window(&win);
+}
+
+void GLManager_OSX::make_current() {
+ if (!_current_window) {
+ return;
+ }
+ if (!_current_window->in_use) {
+ WARN_PRINT("current window not in use!");
+ return;
+ }
+ [_current_window->context makeCurrentContext];
+}
+
+void GLManager_OSX::swap_buffers() {
+ // NO NEED TO CALL SWAP BUFFERS for each window...
+ // see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml
+
+ if (!_current_window) {
+ return;
+ }
+ if (!_current_window->in_use) {
+ WARN_PRINT("current window not in use!");
+ return;
+ }
+ [_current_window->context flushBuffer];
+}
+
+void GLManager_OSX::window_update(DisplayServer::WindowID p_window_id) {
+ if (p_window_id == -1) {
+ return;
+ }
+
+ GLWindow &win = _windows[p_window_id];
+ if (!win.in_use) {
+ return;
+ }
+
+ if (&win == _current_window) {
+ return;
+ }
+
+ [win.context update];
+}
+
+Error GLManager_OSX::initialize() {
+ return OK;
+}
+
+void GLManager_OSX::set_use_vsync(bool p_use) {
+ use_vsync = p_use;
+ CGLContextObj ctx = CGLGetCurrentContext();
+ if (ctx) {
+ GLint swapInterval = p_use ? 1 : 0;
+ CGLSetParameter(ctx, kCGLCPSwapInterval, &swapInterval);
+ use_vsync = p_use;
+ }
+}
+
+bool GLManager_OSX::is_using_vsync() const {
+ return use_vsync;
+}
+
+GLManager_OSX::GLManager_OSX(ContextType p_context_type) {
+ context_type = p_context_type;
+ use_vsync = false;
+ _current_window = nullptr;
+}
+
+GLManager_OSX::~GLManager_OSX() {
+ release_current();
+}
+
+#endif // GLES3_ENABLED
+#endif // OSX
diff --git a/platform/osx/joypad_osx.cpp b/platform/osx/joypad_osx.cpp
index e67d2b0e91..48d165d30b 100644
--- a/platform/osx/joypad_osx.cpp
+++ b/platform/osx/joypad_osx.cpp
@@ -58,6 +58,7 @@ void joypad::free() {
if (ff_device) {
FFDeviceReleaseEffect(ff_device, ff_object);
FFReleaseDevice(ff_device);
+ ff_device = nullptr;
memfree(ff_axes);
memfree(ff_directions);
}
@@ -243,7 +244,7 @@ void JoypadOSX::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) {
if (is_joypad(p_device)) {
configure_joypad(p_device, &new_joypad);
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
- if (IOHIDDeviceGetService != nullptr) {
+ if (IOHIDDeviceGetService) {
#endif
const io_service_t ioservice = IOHIDDeviceGetService(p_device);
if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK) && new_joypad.config_force_feedback(ioservice)) {
@@ -263,7 +264,7 @@ void JoypadOSX::_device_removed(IOReturn p_res, IOHIDDeviceRef p_device) {
input->joy_connection_changed(device_list[device].id, false, "");
device_list.write[device].free();
- device_list.remove(device);
+ device_list.remove_at(device);
}
static String _hex_str(uint8_t p_byte) {
@@ -336,10 +337,10 @@ bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) {
}
// Xbox controller hat values start at 1 rather than 0.
p_joy->offset_hat = vendor == 0x45e &&
- (product_id == 0x0b05 ||
- product_id == 0x02e0 ||
- product_id == 0x02fd ||
- product_id == 0x0b13);
+ (product_id == 0x0b05 ||
+ product_id == 0x02e0 ||
+ product_id == 0x02fd ||
+ product_id == 0x0b13);
return true;
}
@@ -348,6 +349,7 @@ bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) {
{ \
if (ret != FF_OK) { \
FFReleaseDevice(ff_device); \
+ ff_device = nullptr; \
return false; \
} \
}
@@ -367,6 +369,7 @@ bool joypad::config_force_feedback(io_service_t p_service) {
return true;
}
FFReleaseDevice(ff_device);
+ ff_device = nullptr;
return false;
}
#undef FF_ERR
@@ -397,10 +400,10 @@ bool joypad::check_ff_features() {
return false;
}
-static int process_hat_value(int p_min, int p_max, int p_value, bool p_offset_hat) {
+static HatMask process_hat_value(int p_min, int p_max, int p_value, bool p_offset_hat) {
int range = (p_max - p_min + 1);
int value = p_value - p_min;
- int hat_value = HatMask::HAT_MASK_CENTER;
+ HatMask hat_value = HatMask::CENTER;
if (range == 4) {
value *= 2;
}
@@ -410,31 +413,31 @@ static int process_hat_value(int p_min, int p_max, int p_value, bool p_offset_ha
switch (value) {
case 0:
- hat_value = (HatMask)HatMask::HAT_MASK_UP;
+ hat_value = HatMask::UP;
break;
case 1:
- hat_value = (HatMask)(HatMask::HAT_MASK_UP | HatMask::HAT_MASK_RIGHT);
+ hat_value = (HatMask::UP | HatMask::RIGHT);
break;
case 2:
- hat_value = (HatMask)HatMask::HAT_MASK_RIGHT;
+ hat_value = HatMask::RIGHT;
break;
case 3:
- hat_value = (HatMask)(HatMask::HAT_MASK_DOWN | HatMask::HAT_MASK_RIGHT);
+ hat_value = (HatMask::DOWN | HatMask::RIGHT);
break;
case 4:
- hat_value = (HatMask)HatMask::HAT_MASK_DOWN;
+ hat_value = HatMask::DOWN;
break;
case 5:
- hat_value = (HatMask)(HatMask::HAT_MASK_DOWN | HatMask::HAT_MASK_LEFT);
+ hat_value = (HatMask::DOWN | HatMask::LEFT);
break;
case 6:
- hat_value = (HatMask)HatMask::HAT_MASK_LEFT;
+ hat_value = HatMask::LEFT;
break;
case 7:
- hat_value = (HatMask)(HatMask::HAT_MASK_UP | HatMask::HAT_MASK_LEFT);
+ hat_value = (HatMask::UP | HatMask::LEFT);
break;
default:
- hat_value = (HatMask)HatMask::HAT_MASK_CENTER;
+ hat_value = HatMask::CENTER;
break;
}
return hat_value;
@@ -480,8 +483,8 @@ void JoypadOSX::process_joypads() {
for (int j = 0; j < joy.hat_elements.size(); j++) {
rec_element &elem = joy.hat_elements.write[j];
int value = joy.get_hid_element_state(&elem);
- int hat_value = process_hat_value(elem.min, elem.max, value, joy.offset_hat);
- input->joy_hat(joy.id, (HatMask)hat_value);
+ HatMask hat_value = process_hat_value(elem.min, elem.max, value, joy.offset_hat);
+ input->joy_hat(joy.id, hat_value);
}
if (joy.ffservice) {
@@ -601,7 +604,7 @@ JoypadOSX::JoypadOSX(Input *in) {
if (array) {
hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
- if (hid_manager != nullptr) {
+ if (hid_manager) {
config_hid_manager(array);
}
CFRelease(array);
diff --git a/platform/osx/joypad_osx.h b/platform/osx/joypad_osx.h
index c060c3d523..2ba7f0d950 100644
--- a/platform/osx/joypad_osx.h
+++ b/platform/osx/joypad_osx.h
@@ -68,8 +68,8 @@ struct joypad {
io_service_t ffservice = 0; /* Interface for force feedback, 0 = no ff */
FFCONSTANTFORCE ff_constant_force;
- FFDeviceObjectReference ff_device;
- FFEffectObjectReference ff_object;
+ FFDeviceObjectReference ff_device = nullptr;
+ FFEffectObjectReference ff_object = nullptr;
uint64_t ff_timestamp = 0;
LONG *ff_directions = nullptr;
FFEFFECT ff_effect;
@@ -106,7 +106,6 @@ private:
int get_joy_ref(IOHIDDeviceRef p_device) const;
void poll_joypads() const;
- void setup_joypad_objects();
void config_hid_manager(CFArrayRef p_matching_array) const;
void joypad_vibration_start(int p_id, float p_magnitude, float p_duration, uint64_t p_timestamp);
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index df41ccd892..7e02f4e154 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -57,6 +57,8 @@ class OS_OSX : public OS_Unix {
MainLoop *main_loop;
+ static void pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context);
+
public:
String open_with_filename;
@@ -82,6 +84,7 @@ public:
virtual String get_data_path() const override;
virtual String get_cache_path() const override;
virtual String get_bundle_resource_dir() const override;
+ virtual String get_bundle_icon_path() const override;
virtual String get_godot_dir_name() const override;
virtual String get_system_dir(SystemDir p_dir, bool p_shared_storage = true) const override;
@@ -91,6 +94,8 @@ public:
String get_locale() const override;
virtual String get_executable_path() const override;
+ virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
+ virtual Error create_instance(const List<String> &p_arguments, ProcessID *r_child_id = nullptr) override;
virtual String get_unique_id() const override; //++
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index c6e35fee83..39608bdea8 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -178,7 +178,7 @@
class OSXTerminalLogger : public StdLogger {
public:
- virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, ErrorType p_type = ERR_ERROR) {
+ virtual void log_error(const char *p_function, const char *p_file, int p_line, const char *p_code, const char *p_rationale, bool p_editor_notify = false, ErrorType p_type = ERR_ERROR) {
if (!should_log(true)) {
return;
}
@@ -314,17 +314,27 @@ String OS_OSX::get_name() const {
return "macOS";
}
+_FORCE_INLINE_ String _get_framework_executable(const String p_path) {
+ // Append framework executable name, or return as is if p_path is not a framework.
+ DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ if (da->dir_exists(p_path) && da->file_exists(p_path.plus_file(p_path.get_file().get_basename()))) {
+ return p_path.plus_file(p_path.get_file().get_basename());
+ } else {
+ return p_path;
+ }
+}
+
Error OS_OSX::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path) {
- String path = p_path;
+ String path = _get_framework_executable(p_path);
if (!FileAccess::exists(path)) {
- //this code exists so gdnative can load .dylib files from within the executable path
- path = get_executable_path().get_base_dir().plus_file(p_path.get_file());
+ // This code exists so gdnative can load .dylib files from within the executable path.
+ path = _get_framework_executable(get_executable_path().get_base_dir().plus_file(p_path.get_file()));
}
if (!FileAccess::exists(path)) {
- //this code exists so gdnative can load .dylib files from a standard macOS location
- path = get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(p_path.get_file());
+ // This code exists so gdnative can load .dylib files from a standard macOS location.
+ path = _get_framework_executable(get_executable_path().get_base_dir().plus_file("../Frameworks").plus_file(p_path.get_file()));
}
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
@@ -379,14 +389,26 @@ String OS_OSX::get_cache_path() const {
}
String OS_OSX::get_bundle_resource_dir() const {
+ String ret;
+
NSBundle *main = [NSBundle mainBundle];
- NSString *resourcePath = [main resourcePath];
+ if (main) {
+ NSString *resourcePath = [main resourcePath];
+ ret.parse_utf8([resourcePath UTF8String]);
+ }
+ return ret;
+}
- char *utfs = strdup([resourcePath UTF8String]);
+String OS_OSX::get_bundle_icon_path() const {
String ret;
- ret.parse_utf8(utfs);
- free(utfs);
+ NSBundle *main = [NSBundle mainBundle];
+ if (main) {
+ NSString *iconPath = [[main infoDictionary] objectForKey:@"CFBundleIconFile"];
+ if (iconPath) {
+ ret.parse_utf8([iconPath UTF8String]);
+ }
+ }
return ret;
}
@@ -469,14 +491,89 @@ String OS_OSX::get_executable_path() const {
}
}
+Error OS_OSX::create_instance(const List<String> &p_arguments, ProcessID *r_child_id) {
+ // If executable is bundled, always execute editor instances as an app bundle to ensure app window is registered and activated correctly.
+ NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
+ if (nsappname != nil) {
+ String path;
+ path.parse_utf8([[[NSBundle mainBundle] bundlePath] UTF8String]);
+ return create_process(path, p_arguments, r_child_id);
+ } else {
+ return create_process(get_executable_path(), p_arguments, r_child_id);
+ }
+}
+
+Error OS_OSX::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id) {
+ if (@available(macOS 10.15, *)) {
+ // Use NSWorkspace if path is an .app bundle.
+ NSURL *url = [NSURL fileURLWithPath:@(p_path.utf8().get_data())];
+ NSBundle *bundle = [NSBundle bundleWithURL:url];
+ if (bundle) {
+ NSMutableArray *arguments = [[NSMutableArray alloc] init];
+ for (const List<String>::Element *E = p_arguments.front(); E; E = E->next()) {
+ [arguments addObject:[NSString stringWithUTF8String:E->get().utf8().get_data()]];
+ }
+ NSWorkspaceOpenConfiguration *configuration = [[NSWorkspaceOpenConfiguration alloc] init];
+ [configuration setArguments:arguments];
+ [configuration setCreatesNewApplicationInstance:YES];
+ __block dispatch_semaphore_t lock = dispatch_semaphore_create(0);
+ __block Error err = ERR_TIMEOUT;
+ __block pid_t pid = 0;
+ [[NSWorkspace sharedWorkspace] openApplicationAtURL:url
+ configuration:configuration
+ completionHandler:^(NSRunningApplication *app, NSError *error) {
+ if (error) {
+ err = ERR_CANT_FORK;
+ NSLog(@"Failed to execute: %@", error.localizedDescription);
+ } else {
+ pid = [app processIdentifier];
+ err = OK;
+ }
+ dispatch_semaphore_signal(lock);
+ }];
+ dispatch_semaphore_wait(lock, dispatch_time(DISPATCH_TIME_NOW, 20000000000)); // 20 sec timeout, wait for app to launch.
+ dispatch_release(lock);
+
+ if (err == OK) {
+ if (r_child_id) {
+ *r_child_id = (ProcessID)pid;
+ }
+ }
+
+ return err;
+ } else {
+ return OS_Unix::create_process(p_path, p_arguments, r_child_id);
+ }
+ } else {
+ return OS_Unix::create_process(p_path, p_arguments, r_child_id);
+ }
+}
+
+void OS_OSX::pre_wait_observer_cb(CFRunLoopObserverRef p_observer, CFRunLoopActivity p_activiy, void *p_context) {
+ // Prevent main loop from sleeping and redraw window during resize / modal popups.
+
+ if (get_singleton()->get_main_loop()) {
+ Main::force_redraw();
+ if (!Main::is_iterating()) { // Avoid cyclic loop.
+ Main::iteration();
+ }
+ }
+
+ CFRunLoopWakeUp(CFRunLoopGetCurrent()); // Prevent main loop from sleeping.
+}
+
void OS_OSX::run() {
force_quit = false;
- if (!main_loop)
+ if (!main_loop) {
return;
+ }
main_loop->initialize();
+ CFRunLoopObserverRef pre_wait_observer = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, true, 0, &pre_wait_observer_cb, nullptr);
+ CFRunLoopAddObserver(CFRunLoopGetCurrent(), pre_wait_observer, kCFRunLoopCommonModes);
+
bool quit = false;
while (!force_quit && !quit) {
@try {
@@ -492,6 +589,10 @@ void OS_OSX::run() {
ERR_PRINT("NSException: " + String([exception reason].UTF8String));
}
};
+
+ CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), pre_wait_observer, kCFRunLoopCommonModes);
+ CFRelease(pre_wait_observer);
+
main_loop->finalize();
}
diff --git a/platform/osx/platform_config.h b/platform/osx/platform_config.h
index 2d0fd872dc..7bfa466b97 100644
--- a/platform/osx/platform_config.h
+++ b/platform/osx/platform_config.h
@@ -30,4 +30,5 @@
#include <alloca.h>
+#define OPENGL_INCLUDE_H "thirdparty/glad/glad/glad.h"
#define PTHREAD_RENAME_SELF