summaryrefslogtreecommitdiff
path: root/platform/osx
diff options
context:
space:
mode:
Diffstat (limited to 'platform/osx')
-rw-r--r--platform/osx/context_gl_osx.h1
-rw-r--r--platform/osx/context_gl_osx.mm11
-rw-r--r--platform/osx/crash_handler_osx.h1
-rw-r--r--platform/osx/detect.py35
-rw-r--r--platform/osx/dir_access_osx.mm1
-rw-r--r--platform/osx/display_server_osx.h196
-rw-r--r--platform/osx/display_server_osx.mm938
-rw-r--r--platform/osx/export/export.cpp508
-rw-r--r--platform/osx/godot_main_osx.mm6
-rw-r--r--platform/osx/joypad_osx.cpp53
-rw-r--r--platform/osx/joypad_osx.h7
-rw-r--r--platform/osx/logo.pngbin1751 -> 7195 bytes
-rw-r--r--platform/osx/os_osx.h2
-rw-r--r--platform/osx/os_osx.mm47
-rw-r--r--platform/osx/platform_config.h1
-rw-r--r--platform/osx/vulkan_context_osx.h1
-rw-r--r--platform/osx/vulkan_context_osx.mm1
17 files changed, 1070 insertions, 739 deletions
diff --git a/platform/osx/context_gl_osx.h b/platform/osx/context_gl_osx.h
index 7e436c5e36..cce00fb35f 100644
--- a/platform/osx/context_gl_osx.h
+++ b/platform/osx/context_gl_osx.h
@@ -41,7 +41,6 @@
#include <CoreVideo/CoreVideo.h>
class ContextGL_OSX {
-
bool opengl_3_context;
bool use_vsync;
diff --git a/platform/osx/context_gl_osx.mm b/platform/osx/context_gl_osx.mm
index 91d1332d24..2319e9eb1f 100644
--- a/platform/osx/context_gl_osx.mm
+++ b/platform/osx/context_gl_osx.mm
@@ -33,42 +33,34 @@
#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;
@@ -78,12 +70,10 @@ void ContextGL_OSX::set_use_vsync(bool 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);
@@ -161,7 +151,6 @@ Error ContextGL_OSX::initialize() {
}
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;
diff --git a/platform/osx/crash_handler_osx.h b/platform/osx/crash_handler_osx.h
index abd9812596..9970f6045a 100644
--- a/platform/osx/crash_handler_osx.h
+++ b/platform/osx/crash_handler_osx.h
@@ -32,7 +32,6 @@
#define CRASH_HANDLER_OSX_H
class CrashHandler {
-
bool disabled;
public:
diff --git a/platform/osx/detect.py b/platform/osx/detect.py
index 29aa8ece19..272ae1b620 100644
--- a/platform/osx/detect.py
+++ b/platform/osx/detect.py
@@ -24,11 +24,12 @@ def get_opts():
from SCons.Variables import BoolVariable, EnumVariable
return [
- ("osxcross_sdk", "OSXCross SDK version", "darwin14"),
+ ("osxcross_sdk", "OSXCross SDK version", "darwin16"),
("MACOS_SDK_PATH", "Path to the macOS SDK", ""),
BoolVariable(
"use_static_mvk",
- "Link MoltenVK statically as Level-0 driver (better portability) or use Vulkan ICD loader (enables validation layers)",
+ "Link MoltenVK statically as Level-0 driver (better portability) or use Vulkan ICD loader (enables"
+ " validation layers)",
False,
),
EnumVariable("debug_symbols", "Add debugging symbols to release builds", "yes", ("yes", "no", "full")),
@@ -50,9 +51,11 @@ def configure(env):
if env["target"] == "release":
if env["optimize"] == "speed": # optimize for speed (default)
- env.Prepend(CCFLAGS=["-O3", "-fomit-frame-pointer", "-ftree-vectorize", "-msse2"])
+ env.Prepend(CCFLAGS=["-O3", "-fomit-frame-pointer", "-ftree-vectorize"])
else: # optimize for size
- env.Prepend(CCFLAGS=["-Os", "-ftree-vectorize", "-msse2"])
+ env.Prepend(CCFLAGS=["-Os", "-ftree-vectorize"])
+ if env["arch"] != "arm64":
+ env.Prepend(CCFLAGS=["-msse2"])
if env["debug_symbols"] == "yes":
env.Prepend(CCFLAGS=["-g1"])
@@ -72,7 +75,7 @@ def configure(env):
elif env["target"] == "debug":
env.Prepend(CCFLAGS=["-g3"])
- env.Prepend(CPPDEFINES=["DEBUG_ENABLED", "DEBUG_MEMORY_ENABLED"])
+ env.Prepend(CPPDEFINES=["DEBUG_ENABLED"])
## Architecture
@@ -86,9 +89,16 @@ def configure(env):
if "OSXCROSS_ROOT" in os.environ:
env["osxcross"] = True
+ if env["arch"] == "arm64":
+ print("Building for macOS 10.15+, platform arm64.")
+ env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15", "-target", "arm64-apple-macos10.15"])
+ env.Append(LINKFLAGS=["-arch", "arm64", "-mmacosx-version-min=10.15", "-target", "arm64-apple-macos10.15"])
+ else:
+ 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"])
+
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":
mpprefix = os.environ.get("MACPORTS_PREFIX", "/opt/local")
mpclangver = env["macports_clang"]
@@ -109,7 +119,10 @@ def configure(env):
else: # osxcross build
root = os.environ.get("OSXCROSS_ROOT", 0)
- basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
+ if env["arch"] == "arm64":
+ basecmd = root + "/target/bin/arm64-apple-" + env["osxcross_sdk"] + "-"
+ else:
+ basecmd = root + "/target/bin/x86_64-apple-" + env["osxcross_sdk"] + "-"
ccache_path = os.environ.get("CCACHE")
if ccache_path is None:
@@ -148,7 +161,8 @@ def configure(env):
## Dependencies
if env["builtin_libtheora"]:
- env["x86_libtheora_opt_gcc"] = True
+ if env["arch"] != "arm64":
+ env["x86_libtheora_opt_gcc"] = True
## Flags
@@ -189,6 +203,3 @@ def configure(env):
env.Append(LIBS=["vulkan"])
# env.Append(CPPDEFINES=['GLES_ENABLED', 'OPENGL_ENABLED'])
-
- env.Append(CCFLAGS=["-mmacosx-version-min=10.12"])
- env.Append(LINKFLAGS=["-mmacosx-version-min=10.12"])
diff --git a/platform/osx/dir_access_osx.mm b/platform/osx/dir_access_osx.mm
index 66ea380903..7791ba5407 100644
--- a/platform/osx/dir_access_osx.mm
+++ b/platform/osx/dir_access_osx.mm
@@ -38,7 +38,6 @@
#include <Foundation/Foundation.h>
String DirAccessOSX::fix_unicode_name(const char *p_name) const {
-
String fname;
NSString *nsstr = [[NSString stringWithUTF8String:p_name] precomposedStringWithCanonicalMapping];
diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h
index 86ceb51763..d8f3f81ff6 100644
--- a/platform/osx/display_server_osx.h
+++ b/platform/osx/display_server_osx.h
@@ -33,7 +33,7 @@
#define BitMap _QDBitMap // Suppress deprecated QuickDraw definition.
-#include "core/input/input_filter.h"
+#include "core/input/input.h"
#include "servers/display_server.h"
#if defined(OPENGL_ENABLED)
@@ -86,6 +86,14 @@ public:
uint32_t unicode;
};
+ struct WarpEvent {
+ NSTimeInterval timestamp;
+ NSPoint delta;
+ };
+
+ List<WarpEvent> warp_events;
+ NSTimeInterval last_warp = 0;
+
Vector<KeyEvent> key_event_buffer;
int key_event_pos;
@@ -124,6 +132,7 @@ public:
bool on_top = false;
bool borderless = false;
bool resize_disabled = false;
+ bool no_focus = false;
};
Point2i im_selection;
@@ -142,7 +151,6 @@ public:
void _set_window_per_pixel_transparency_enabled(bool p_enabled, WindowID p_window);
- float _display_scale(id screen) const;
Point2i _get_screens_origin() const;
Point2i _get_native_screen_position(int p_screen) const;
@@ -169,132 +177,138 @@ public:
bool in_dispatch_input_event = false;
public:
- virtual bool has_feature(Feature p_feature) const;
- virtual String get_name() const;
+ virtual bool has_feature(Feature p_feature) const override;
+ virtual String get_name() const override;
- virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant());
- virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant());
- virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu);
- virtual void global_menu_add_separator(const String &p_menu_root);
+ virtual void global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant()) override;
+ virtual void global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback, const Variant &p_tag = Variant()) override;
+ virtual void global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu) override;
+ virtual void global_menu_add_separator(const String &p_menu_root) override;
- virtual bool global_menu_is_item_checked(const String &p_menu_root, int p_idx) const;
- virtual bool global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const;
- virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx);
- virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx);
- virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx);
- virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx);
+ virtual bool global_menu_is_item_checked(const String &p_menu_root, int p_idx) const override;
+ virtual bool global_menu_is_item_checkable(const String &p_menu_root, int p_idx) const override;
+ virtual Callable global_menu_get_item_callback(const String &p_menu_root, int p_idx) override;
+ virtual Variant global_menu_get_item_tag(const String &p_menu_root, int p_idx) override;
+ virtual String global_menu_get_item_text(const String &p_menu_root, int p_idx) override;
+ virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx) override;
- virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked);
- virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable);
- virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback);
- virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag);
- virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text);
- virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu);
+ virtual void global_menu_set_item_checked(const String &p_menu_root, int p_idx, bool p_checked) override;
+ virtual void global_menu_set_item_checkable(const String &p_menu_root, int p_idx, bool p_checkable) override;
+ virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) override;
+ virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) override;
+ virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text) override;
+ virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu) override;
- virtual int global_menu_get_item_count(const String &p_menu_root) const;
+ virtual int global_menu_get_item_count(const String &p_menu_root) const override;
- virtual void global_menu_remove_item(const String &p_menu_root, int p_idx);
- virtual void global_menu_clear(const String &p_menu_root);
+ virtual void global_menu_remove_item(const String &p_menu_root, int p_idx) override;
+ virtual void global_menu_clear(const String &p_menu_root) override;
- virtual void alert(const String &p_alert, const String &p_title = "ALERT!");
- virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback);
- virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback);
+ virtual void alert(const String &p_alert, const String &p_title = "ALERT!") override;
+ virtual Error dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) override;
+ virtual Error dialog_input_text(String p_title, String p_description, String p_partial, const Callable &p_callback) override;
- virtual void mouse_set_mode(MouseMode p_mode);
- virtual MouseMode mouse_get_mode() const;
+ virtual void mouse_set_mode(MouseMode p_mode) override;
+ virtual MouseMode mouse_get_mode() const override;
- virtual void mouse_warp_to_position(const Point2i &p_to);
- virtual Point2i mouse_get_position() const;
- virtual Point2i mouse_get_absolute_position() const;
- virtual int mouse_get_button_state() const;
+ virtual void mouse_warp_to_position(const Point2i &p_to) override;
+ virtual Point2i mouse_get_position() const override;
+ virtual Point2i mouse_get_absolute_position() const override;
+ virtual int mouse_get_button_state() const override;
- virtual void clipboard_set(const String &p_text);
- virtual String clipboard_get() const;
+ virtual void clipboard_set(const String &p_text) override;
+ virtual String clipboard_get() const override;
- virtual int get_screen_count() const;
- virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
- virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const;
+ virtual int get_screen_count() const override;
+ virtual Point2i screen_get_position(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual Size2i screen_get_size(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual int screen_get_dpi(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual float screen_get_scale(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
+ virtual float screen_get_max_scale() const override;
+ virtual Rect2i screen_get_usable_rect(int p_screen = SCREEN_OF_MAIN_WINDOW) const override;
- virtual Vector<int> get_window_list() const;
+ virtual Vector<int> get_window_list() const override;
- virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i & = Rect2i());
- virtual void delete_sub_window(WindowID p_id);
+ virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i()) override;
+ virtual void show_window(WindowID p_id) override;
+ virtual void delete_sub_window(WindowID p_id) override;
- virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_drop_files_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID);
+ virtual int window_get_current_screen(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_current_screen(int p_screen, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID);
+ virtual Point2i window_get_position(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual void window_set_position(const Point2i &p_position, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual void window_set_transient(WindowID p_window, WindowID p_parent);
+ virtual void window_set_transient(WindowID p_window, WindowID p_parent) override;
- virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_max_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_max_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_min_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_min_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID);
- virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const;
- virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_size(const Size2i p_size, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual Size2i window_get_size(WindowID p_window = MAIN_WINDOW_ID) const override;
+ virtual Size2i window_get_real_size(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID);
- virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_mode(WindowMode p_mode, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual WindowMode window_get_mode(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool window_is_maximize_allowed(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID);
- virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual void window_set_flag(WindowFlags p_flag, bool p_enabled, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_get_flag(WindowFlags p_flag, WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
- virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const;
+ virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
- virtual bool can_any_window_draw() const;
+ virtual bool can_any_window_draw() const override;
- virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID);
- virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID);
+ virtual void window_set_ime_active(const bool p_active, WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual void window_set_ime_position(const Point2i &p_pos, WindowID p_window = MAIN_WINDOW_ID) override;
- virtual WindowID get_window_at_screen_position(const Point2i &p_position) const;
+ virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override;
- virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID);
- virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const;
+ 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 Point2i ime_get_selection() const;
- virtual String ime_get_text() const;
+ virtual Point2i ime_get_selection() const override;
+ virtual String ime_get_text() const override;
- virtual void cursor_set_shape(CursorShape p_shape);
- virtual CursorShape cursor_get_shape() const;
- virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2());
+ virtual void cursor_set_shape(CursorShape p_shape) override;
+ virtual CursorShape cursor_get_shape() const override;
+ virtual void cursor_set_custom_image(const RES &p_cursor, CursorShape p_shape = CURSOR_ARROW, const Vector2 &p_hotspot = Vector2()) override;
- virtual bool get_swap_ok_cancel();
+ virtual bool get_swap_cancel_ok() override;
- virtual LatinKeyboardVariant get_latin_keyboard_variant() const;
+ virtual int keyboard_get_layout_count() const override;
+ virtual int keyboard_get_current_layout() const override;
+ 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 void process_events();
- virtual void force_process_and_drop_events();
+ virtual void process_events() override;
+ virtual void force_process_and_drop_events() override;
- virtual void release_rendering_thread();
- virtual void make_rendering_thread();
- virtual void swap_buffers();
+ virtual void release_rendering_thread() override;
+ virtual void make_rendering_thread() override;
+ virtual void swap_buffers() override;
- virtual void set_native_icon(const String &p_filename);
- virtual void set_icon(const Ref<Image> &p_icon);
+ virtual void set_native_icon(const String &p_filename) override;
+ virtual void set_icon(const Ref<Image> &p_icon) override;
- virtual void console_set_visible(bool p_enabled);
- virtual bool is_console_visible() const;
+ virtual void console_set_visible(bool p_enabled) override;
+ virtual bool is_console_visible() const override;
static DisplayServer *create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error);
static Vector<String> get_rendering_drivers_func();
diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm
index 074fc3be0d..3b82950224 100644
--- a/platform/osx/display_server_osx.mm
+++ b/platform/osx/display_server_osx.mm
@@ -45,8 +45,9 @@
#include <IOKit/hid/IOHIDLib.h>
#if defined(OPENGL_ENABLED)
-#include "drivers/gles2/rasterizer_gles2.h"
//TODO - reimplement OpenGLES
+
+#import <AppKit/NSOpenGLView.h>
#endif
#if defined(VULKAN_ENABLED)
@@ -55,6 +56,10 @@
#include <QuartzCore/CAMetalLayer.h>
#endif
+#ifndef NSAppKitVersionNumber10_14
+#define NSAppKitVersionNumber10_14 1671
+#endif
+
#define DS_OSX ((DisplayServerOSX *)(DisplayServerOSX::get_singleton()))
static void _get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWithModifiers> r_state) {
@@ -64,13 +69,13 @@ static void _get_key_modifier_state(unsigned int p_osx_state, Ref<InputEventWith
r_state->set_metakey((p_osx_state & NSEventModifierFlagCommand));
}
-static Vector2i _get_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPoint p_locationInWindow, CGFloat p_backingScaleFactor) {
+static Vector2i _get_mouse_pos(DisplayServerOSX::WindowData &p_wd, NSPoint p_locationInWindow) {
const NSRect contentRect = [p_wd.window_view frame];
- const NSPoint p = p_locationInWindow;
- p_wd.mouse_pos.x = p.x * p_backingScaleFactor;
- p_wd.mouse_pos.y = (contentRect.size.height - p.y) * p_backingScaleFactor;
+ const float scale = DS_OSX->screen_get_max_scale();
+ p_wd.mouse_pos.x = p_locationInWindow.x * scale;
+ p_wd.mouse_pos.y = (contentRect.size.height - p_locationInWindow.y) * scale;
DS_OSX->last_mouse_pos = p_wd.mouse_pos;
- InputFilter::get_singleton()->set_mouse_position(p_wd.mouse_pos);
+ Input::get_singleton()->set_mouse_position(p_wd.mouse_pos);
return p_wd.mouse_pos;
}
@@ -120,17 +125,18 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
k->set_physical_keycode(KEY_PERIOD);
k->set_echo([event isARepeat]);
- InputFilter::get_singleton()->accumulate_input_event(k);
+ Input::get_singleton()->accumulate_input_event(k);
}
}
// From http://cocoadev.com/index.pl?GameKeyboardHandlingAlmost
// This works around an AppKit bug, where key up events while holding
// down the command key don't get sent to the key window.
- if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand))
+ if ([event type] == NSEventTypeKeyUp && ([event modifierFlags] & NSEventModifierFlagCommand)) {
[[self keyWindow] sendEvent:event];
- else
+ } else {
[super sendEvent:event];
+ }
}
@end
@@ -145,6 +151,7 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
Variant meta;
bool checkable;
}
+
@end
@implementation GlobalMenuItem
@@ -192,9 +199,22 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
}
+- (void)applicationDidResignActive:(NSNotification *)notification {
+ if (OS_OSX::get_singleton()->get_main_loop()) {
+ OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
+ }
+}
+
+- (void)applicationDidBecomeActive:(NSNotification *)notification {
+ if (OS_OSX::get_singleton()->get_main_loop()) {
+ OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
+ }
+}
+
- (void)globalMenuCallback:(id)sender {
- if (![sender representedObject])
+ if (![sender representedObject]) {
return;
+ }
GlobalMenuItem *value = [sender representedObject];
@@ -247,8 +267,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)showAbout:(id)sender {
- if (OS_OSX::get_singleton()->get_main_loop())
+ if (OS_OSX::get_singleton()->get_main_loop()) {
OS_OSX::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_ABOUT);
+ }
}
@end
@@ -273,13 +294,17 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (BOOL)windowShouldClose:(id)sender {
- ERR_FAIL_COND_V(!DS_OSX->windows.has(window_id), YES);
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return YES;
+ }
DS_OSX->_send_window_event(DS_OSX->windows[window_id], DisplayServerOSX::WINDOW_EVENT_CLOSE_REQUEST);
return NO;
}
- (void)windowWillClose:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
while (wd.transient_children.size()) {
@@ -297,6 +322,11 @@ 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
+ }
+#endif
#ifdef VULKAN_ENABLED
if (DS_OSX->rendering_driver == "vulkan") {
DS_OSX->context_vulkan->window_destroy(window_id);
@@ -305,7 +335,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidEnterFullScreen:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
wd.fullscreen = true;
@@ -315,28 +347,32 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidExitFullScreen:(NSNotification *)notification {
- if (!DS_OSX || !DS_OSX->windows.has(window_id))
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
wd.fullscreen = false;
+ const float scale = DS_OSX->screen_get_max_scale();
if (wd.min_size != Size2i()) {
- Size2i size = wd.min_size / DS_OSX->_display_scale([wd.window_object screen]);
+ Size2i size = wd.min_size / scale;
[wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)];
}
if (wd.max_size != Size2i()) {
- Size2i size = wd.max_size / DS_OSX->_display_scale([wd.window_object screen]);
+ Size2i size = wd.max_size / scale;
[wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)];
}
- if (wd.resize_disabled)
+ if (wd.resize_disabled) {
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
+ }
}
- (void)windowDidChangeBackingProperties:(NSNotification *)notification {
- if (!DisplayServerOSX::get_singleton())
+ if (!DisplayServerOSX::get_singleton()) {
return;
+ }
ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
@@ -344,60 +380,50 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
CGFloat newBackingScaleFactor = [wd.window_object backingScaleFactor];
CGFloat oldBackingScaleFactor = [[[notification userInfo] objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue];
-#if defined(OPENGL_ENABLED)
- if (DS_OSX->rendering_driver == "opengl_es") {
- //TODO - reimplement OpenGLES
- if (OS_OSX::get_singleton()->is_hidpi_allowed()) {
- [wd.window_view setWantsBestResolutionOpenGLSurface:YES];
- } else {
- [wd.window_view setWantsBestResolutionOpenGLSurface:NO];
- }
- }
-#endif
-
if (newBackingScaleFactor != oldBackingScaleFactor) {
//Set new display scale and window size
- float newDisplayScale = OS_OSX::get_singleton()->is_hidpi_allowed() ? newBackingScaleFactor : 1.0;
-
+ const float scale = DS_OSX->screen_get_max_scale();
const NSRect contentRect = [wd.window_view frame];
- wd.size.width = contentRect.size.width * newDisplayScale;
- wd.size.height = contentRect.size.height * newDisplayScale;
+ wd.size.width = contentRect.size.width * scale;
+ wd.size.height = contentRect.size.height * scale;
DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_DPI_CHANGE);
-#if defined(VULKAN_ENABLED)
- if (DS_OSX->rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- layer.contentsScale = DS_OSX->_display_scale([wd.window_object screen]);
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ layer.contentsScale = scale;
}
-#endif
+
//Force window resize event
[self windowDidResize:notification];
}
}
- (void)windowDidResize:(NSNotification *)notification {
- if (!DS_OSX || !DS_OSX->windows.has(window_id))
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
+ const NSRect contentRect = [wd.window_view frame];
+
+ const float scale = DS_OSX->screen_get_max_scale();
+ wd.size.width = contentRect.size.width * scale;
+ wd.size.height = contentRect.size.height * scale;
+
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ layer.contentsScale = scale;
+ }
+
#if defined(OPENGL_ENABLED)
if (DS_OSX->rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2->update();
}
#endif
- const NSRect contentRect = [wd.window_view frame];
-
- float displayScale = DS_OSX->_display_scale([wd.window_object screen]);
- wd.size.width = contentRect.size.width * displayScale;
- wd.size.height = contentRect.size.height * displayScale;
-
#if defined(VULKAN_ENABLED)
if (DS_OSX->rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- layer.contentsScale = displayScale;
DS_OSX->context_vulkan->window_resize(window_id, wd.size.width, wd.size.height);
}
#endif
@@ -420,23 +446,39 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidMove:(NSNotification *)notification {
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
+ DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
+
DS_OSX->_release_pressed_events();
+
+ if (!wd.rect_changed_callback.is_null()) {
+ Variant size = Rect2i(DS_OSX->window_get_position(window_id), DS_OSX->window_get_size(window_id));
+ Variant *sizep = &size;
+ Variant ret;
+ Callable::CallError ce;
+ wd.rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce);
+ }
}
- (void)windowDidBecomeKey:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [wd.window_view backingScaleFactor] : 1.0;
- _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream], backingScaleFactor);
- InputFilter::get_singleton()->set_mouse_position(wd.mouse_pos);
+ _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
+ Input::get_singleton()->set_mouse_position(wd.mouse_pos);
DS_OSX->window_focused = true;
DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN);
}
- (void)windowDidResignKey:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
DS_OSX->window_focused = false;
@@ -446,7 +488,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidMiniaturize:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
DS_OSX->window_focused = false;
@@ -456,7 +500,9 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)windowDidDeminiaturize:(NSNotification *)notification {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
+ if (!DS_OSX || !DS_OSX->windows.has(window_id)) {
+ return;
+ }
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
DS_OSX->window_focused = true;
@@ -497,6 +543,12 @@ 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];
@@ -507,20 +559,17 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
}
- (void)updateLayer {
-#if defined(VULKAN_ENABLED)
- if (DS_OSX->rendering_driver == "vulkan") {
- [super updateLayer];
- }
-#endif
#if defined(OPENGL_ENABLED)
if (DS_OSX->rendering_driver == "opengl_es") {
- ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
- DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
-
- wd.context_gles2->update();
+ [super updateLayer];
//TODO - reimplement OpenGLES
}
#endif
+#if defined(VULKAN_ENABLED)
+ if (DS_OSX->rendering_driver == "vulkan") {
+ [super updateLayer];
+ }
+#endif
}
- (BOOL)wantsUpdateLayer {
@@ -532,7 +581,11 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) {
trackingArea = nil;
imeInputEventInProgress = false;
[self updateTrackingAreas];
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ [self registerForDraggedTypes:[NSArray arrayWithObject:NSPasteboardTypeFileURL]];
+#else
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
+#endif
markedText = [[NSMutableAttributedString alloc] init];
return self;
}
@@ -581,8 +634,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
}
- (void)doCommandBySelector:(SEL)aSelector {
- if ([self respondsToSelector:aSelector])
+ if ([self respondsToSelector:aSelector]) {
[self performSelector:aSelector];
+ }
}
- (void)unmarkText {
@@ -617,8 +671,8 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
const NSRect contentRect = [wd.window_view frame];
- float displayScale = DS_OSX->_display_scale([wd.window_object screen]);
- NSRect pointInWindowRect = NSMakeRect(wd.im_position.x / displayScale, contentRect.size.height - (wd.im_position.y / displayScale) - 1, 0, 0);
+ const float scale = DS_OSX->screen_get_max_scale();
+ NSRect pointInWindowRect = NSMakeRect(wd.im_position.x / scale, contentRect.size.height - (wd.im_position.y / scale) - 1, 0, 0);
NSPoint pointOnScreen = [wd.window_object convertRectToScreen:pointInWindowRect].origin;
return NSMakeRect(pointOnScreen.x, pointOnScreen.y, 0, 0);
@@ -657,8 +711,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
for (i = 0; i < length; i++) {
const unichar codepoint = [characters characterAtIndex:i];
- if ((codepoint & 0xFF00) == 0xF700)
+ if ((codepoint & 0xFF00) == 0xF700) {
continue;
+ }
DisplayServerOSX::KeyEvent ke;
@@ -689,11 +744,19 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
NSPasteboard *pboard = [sender draggingPasteboard];
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ NSArray<NSURL *> *filenames = [pboard propertyListForType:NSPasteboardTypeFileURL];
+#else
NSArray *filenames = [pboard propertyListForType:NSFilenamesPboardType];
+#endif
Vector<String> files;
for (NSUInteger i = 0; i < filenames.count; i++) {
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
+ NSString *ns = [[filenames objectAtIndex:i] path];
+#else
NSString *ns = [filenames objectAtIndex:i];
+#endif
char *utfs = strdup([ns UTF8String]);
String ret;
ret.parse_utf8(utfs);
@@ -717,6 +780,12 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
}
- (BOOL)canBecomeKeyView {
+ if (DS_OSX->windows.has(window_id)) {
+ DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
+ if (wd.no_focus) {
+ return NO;
+ }
+ }
return YES;
}
@@ -743,8 +812,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
Ref<InputEventMouseButton> mb;
mb.instance();
mb->set_window_id(window_id);
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0;
- const Vector2 pos = _get_mouse_pos(wd, [event locationInWindow], backingScaleFactor);
+ const Vector2 pos = _get_mouse_pos(wd, [event locationInWindow]);
_get_key_modifier_state([event modifierFlags], mb);
mb->set_button_index(index);
mb->set_pressed(pressed);
@@ -755,7 +823,7 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
mb->set_doubleclick([event clickCount] == 2);
}
- InputFilter::get_singleton()->accumulate_input_event(mb);
+ Input::get_singleton()->accumulate_input_event(mb);
}
- (void)mouseDown:(NSEvent *)event {
@@ -790,13 +858,58 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
+ NSPoint delta = NSMakePoint([event deltaX], [event deltaY]);
+ NSPoint mpos = [event locationInWindow];
+
+ if (DS_OSX->mouse_mode == DisplayServer::MOUSE_MODE_CONFINED) {
+ // Discard late events
+ if (([event timestamp]) < DS_OSX->last_warp) {
+ return;
+ }
+
+ // Warp affects next event delta, subtract previous warp deltas
+ List<DisplayServerOSX::WarpEvent>::Element *F = DS_OSX->warp_events.front();
+ while (F) {
+ if (F->get().timestamp < [event timestamp]) {
+ List<DisplayServerOSX::WarpEvent>::Element *E = F;
+ delta.x -= E->get().delta.x;
+ delta.y -= E->get().delta.y;
+ F = F->next();
+ DS_OSX->warp_events.erase(E);
+ } else {
+ F = F->next();
+ }
+ }
+
+ // Confine mouse position to the window, and update delta
+ NSRect frame = [wd.window_object frame];
+ NSPoint conf_pos = mpos;
+ conf_pos.x = CLAMP(conf_pos.x + delta.x, 0.f, frame.size.width);
+ conf_pos.y = CLAMP(conf_pos.y - delta.y, 0.f, frame.size.height);
+ delta.x = conf_pos.x - mpos.x;
+ delta.y = mpos.y - conf_pos.y;
+ mpos = conf_pos;
+
+ // Move mouse cursor
+ NSRect pointInWindowRect = NSMakeRect(conf_pos.x, conf_pos.y, 0, 0);
+ conf_pos = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin;
+ conf_pos.y = CGDisplayBounds(CGMainDisplayID()).size.height - conf_pos.y;
+ CGWarpMouseCursorPosition(conf_pos);
+
+ // Save warp data
+ DS_OSX->last_warp = [[NSProcessInfo processInfo] systemUptime];
+ DisplayServerOSX::WarpEvent ev;
+ ev.timestamp = DS_OSX->last_warp;
+ ev.delta = delta;
+ DS_OSX->warp_events.push_back(ev);
+ }
+
Ref<InputEventMouseMotion> mm;
mm.instance();
mm->set_window_id(window_id);
mm->set_button_mask(DS_OSX->last_button_state);
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0;
- const Vector2i pos = _get_mouse_pos(wd, [event locationInWindow], backingScaleFactor);
+ const Vector2i pos = _get_mouse_pos(wd, mpos);
mm->set_position(pos);
mm->set_pressure([event pressure]);
if ([event subtype] == NSEventSubtypeTabletPoint) {
@@ -804,15 +917,13 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
mm->set_tilt(Vector2(p.x, p.y));
}
mm->set_global_position(pos);
- mm->set_speed(InputFilter::get_singleton()->get_last_mouse_speed());
- Vector2i relativeMotion = Vector2i();
- relativeMotion.x = [event deltaX] * backingScaleFactor;
- relativeMotion.y = [event deltaY] * backingScaleFactor;
+ mm->set_speed(Input::get_singleton()->get_last_mouse_speed());
+ const Vector2i relativeMotion = Vector2i(delta.x, delta.y) * DS_OSX->screen_get_max_scale();
mm->set_relative(relativeMotion);
_get_key_modifier_state([event modifierFlags], mm);
- InputFilter::get_singleton()->set_mouse_position(wd.mouse_pos);
- InputFilter::get_singleton()->accumulate_input_event(mm);
+ Input::get_singleton()->set_mouse_position(wd.mouse_pos);
+ Input::get_singleton()->accumulate_input_event(mm);
}
- (void)rightMouseDown:(NSEvent *)event {
@@ -859,16 +970,18 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
- if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED)
+ if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED) {
DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_EXIT);
+ }
}
- (void)mouseEntered:(NSEvent *)event {
ERR_FAIL_COND(!DS_OSX->windows.has(window_id));
DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id];
- if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED)
+ if (DS_OSX->mouse_mode != DisplayServer::MOUSE_MODE_CAPTURED) {
DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_MOUSE_ENTER);
+ }
DisplayServer::CursorShape p_shape = DS_OSX->cursor_shape;
DS_OSX->cursor_shape = DisplayServer::CURSOR_MAX;
@@ -883,11 +996,10 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
ev.instance();
ev->set_window_id(window_id);
_get_key_modifier_state([event modifierFlags], ev);
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0;
- ev->set_position(_get_mouse_pos(wd, [event locationInWindow], backingScaleFactor));
+ ev->set_position(_get_mouse_pos(wd, [event locationInWindow]));
ev->set_factor([event magnification] + 1.0);
- InputFilter::get_singleton()->accumulate_input_event(ev);
+ Input::get_singleton()->accumulate_input_event(ev);
}
- (void)viewDidChangeBackingProperties {
@@ -900,24 +1012,14 @@ static void _mouseDownEvent(DisplayServer::WindowID window_id, NSEvent *event, i
[trackingArea release];
}
- NSTrackingAreaOptions options =
- NSTrackingMouseEnteredAndExited |
- NSTrackingActiveInKeyWindow |
- NSTrackingCursorUpdate |
- NSTrackingInVisibleRect;
-
- trackingArea = [[NSTrackingArea alloc]
- initWithRect:[self bounds]
- options:options
- owner:self
- userInfo:nil];
+ NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingCursorUpdate | NSTrackingInVisibleRect;
+ trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:options owner:self userInfo:nil];
[self addTrackingArea:trackingArea];
[super updateTrackingAreas];
}
static bool isNumpadKey(unsigned int key) {
-
static const unsigned int table[] = {
0x41, /* kVK_ANSI_KeypadDecimal */
0x43, /* kVK_ANSI_KeypadMultiply */
@@ -941,8 +1043,9 @@ static bool isNumpadKey(unsigned int key) {
0x00
};
for (int i = 0; table[i] != 0; i++) {
- if (key == table[i])
+ if (key == table[i]) {
return true;
+ }
}
return false;
}
@@ -950,7 +1053,6 @@ static bool isNumpadKey(unsigned int key) {
// Translates a OS X keycode to a Godot keycode
//
static int translateKey(unsigned int key) {
-
// Keyboard symbol translation table
static const unsigned int table[128] = {
/* 00 */ KEY_A,
@@ -1083,8 +1185,9 @@ static int translateKey(unsigned int key) {
/* 7f */ KEY_UNKNOWN,
};
- if (key >= 128)
+ if (key >= 128) {
return KEY_UNKNOWN;
+ }
return table[key];
}
@@ -1153,16 +1256,19 @@ static const _KeyCodeMap _keycodes[55] = {
};
static int remapKey(unsigned int key, unsigned int state) {
- if (isNumpadKey(key))
+ if (isNumpadKey(key)) {
return translateKey(key);
+ }
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
- if (!currentKeyboard)
+ if (!currentKeyboard) {
return translateKey(key);
+ }
CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
- if (!layoutData)
+ if (!layoutData) {
return translateKey(key);
+ }
const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
@@ -1235,8 +1341,9 @@ static int remapKey(unsigned int key, unsigned int state) {
}
// Pass events to IME handler
- if (wd.im_active)
+ if (wd.im_active) {
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
+ }
}
- (void)flagsChanged:(NSEvent *)event {
@@ -1353,7 +1460,7 @@ inline void sendScrollEvent(DisplayServer::WindowID window_id, int button, doubl
DS_OSX->last_button_state |= mask;
sc->set_button_mask(DS_OSX->last_button_state);
- InputFilter::get_singleton()->accumulate_input_event(sc);
+ Input::get_singleton()->accumulate_input_event(sc);
sc.instance();
sc->set_window_id(window_id);
@@ -1365,7 +1472,7 @@ inline void sendScrollEvent(DisplayServer::WindowID window_id, int button, doubl
DS_OSX->last_button_state &= ~mask;
sc->set_button_mask(DS_OSX->last_button_state);
- InputFilter::get_singleton()->accumulate_input_event(sc);
+ Input::get_singleton()->accumulate_input_event(sc);
}
inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy, int modifierFlags) {
@@ -1380,7 +1487,7 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy
pg->set_position(wd.mouse_pos);
pg->set_delta(Vector2(-dx, -dy));
- InputFilter::get_singleton()->accumulate_input_event(pg);
+ Input::get_singleton()->accumulate_input_event(pg);
}
- (void)scrollWheel:(NSEvent *)event {
@@ -1389,8 +1496,7 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy
double deltaX, deltaY;
- const CGFloat backingScaleFactor = (OS::get_singleton()->is_hidpi_allowed()) ? [[event window] backingScaleFactor] : 1.0;
- _get_mouse_pos(wd, [event locationInWindow], backingScaleFactor);
+ _get_mouse_pos(wd, [event locationInWindow]);
deltaX = [event scrollingDeltaX];
deltaY = [event scrollingDeltaY];
@@ -1420,12 +1526,32 @@ inline void sendPanEvent(DisplayServer::WindowID window_id, double dx, double dy
@interface GodotWindow : NSWindow {
}
+
@end
@implementation GodotWindow
- (BOOL)canBecomeKeyWindow {
// Required for NSBorderlessWindowMask windows
+ for (Map<DisplayServer::WindowID, DisplayServerOSX::WindowData>::Element *E = DS_OSX->windows.front(); E; E = E->next()) {
+ if (E->get().window_object == self) {
+ if (E->get().no_focus) {
+ return NO;
+ }
+ }
+ }
+ return YES;
+}
+
+- (BOOL)canBecomeMainWindow {
+ // Required for NSBorderlessWindowMask windows
+ for (Map<DisplayServer::WindowID, DisplayServerOSX::WindowData>::Element *E = DS_OSX->windows.front(); E; E = E->next()) {
+ if (E->get().window_object == self) {
+ if (E->get().no_focus) {
+ return NO;
+ }
+ }
+ }
return YES;
}
@@ -1452,6 +1578,7 @@ bool DisplayServerOSX::has_feature(Feature p_feature) const {
case FEATURE_HIDPI:
case FEATURE_ICON:
case FEATURE_NATIVE_ICON:
+ //case FEATURE_KEEP_SCREEN_ON:
case FEATURE_SWAP_BUFFERS:
return true;
default: {
@@ -1652,7 +1779,8 @@ String DisplayServerOSX::global_menu_get_item_submenu(const String &p_menu_root,
const NSMenu *sub_menu = [menu_item submenu];
if (sub_menu) {
for (Map<String, NSMenu *>::Element *E = submenu.front(); E; E = E->next()) {
- if (E->get() == sub_menu) return E->key();
+ if (E->get() == sub_menu)
+ return E->key();
}
}
}
@@ -1815,8 +1943,12 @@ void DisplayServerOSX::alert(const String &p_alert, const String &p_title) {
[window setInformativeText:ns_alert];
[window setAlertStyle:NSAlertStyleWarning];
+ id key_window = [[NSApplication sharedApplication] keyWindow];
[window runModal];
[window release];
+ if (key_window) {
+ [key_window makeKeyAndOrderFront:nil];
+ }
}
Error DisplayServerOSX::dialog_show(String p_title, String p_description, Vector<String> p_buttons, const Callable &p_callback) {
@@ -1896,23 +2028,32 @@ Error DisplayServerOSX::dialog_input_text(String p_title, String p_description,
void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) {
_THREAD_SAFE_METHOD_
- if (p_mode == mouse_mode)
+ if (p_mode == mouse_mode) {
return;
+ }
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."
// https://developer.apple.com/library/mac/documentation/graphicsimaging/reference/Quartz_Services_Ref/Reference/reference.html
- CGDisplayHideCursor(kCGDirectMainDisplay);
+ if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
+ CGDisplayHideCursor(kCGDirectMainDisplay);
+ }
CGAssociateMouseAndMouseCursorPosition(false);
} else if (p_mode == MOUSE_MODE_HIDDEN) {
- CGDisplayHideCursor(kCGDirectMainDisplay);
+ if (mouse_mode == MOUSE_MODE_VISIBLE || mouse_mode == MOUSE_MODE_CONFINED) {
+ CGDisplayHideCursor(kCGDirectMainDisplay);
+ }
CGAssociateMouseAndMouseCursorPosition(true);
+ } else if (p_mode == MOUSE_MODE_CONFINED) {
+ CGDisplayShowCursor(kCGDirectMainDisplay);
+ CGAssociateMouseAndMouseCursorPosition(false);
} else {
CGDisplayShowCursor(kCGDirectMainDisplay);
CGAssociateMouseAndMouseCursorPosition(true);
}
+ warp_events.clear();
mouse_mode = p_mode;
}
@@ -1930,8 +2071,8 @@ void DisplayServerOSX::mouse_warp_to_position(const Point2i &p_to) {
//local point in window coords
const NSRect contentRect = [wd.window_view frame];
- float displayScale = _display_scale([wd.window_object screen]);
- NSRect pointInWindowRect = NSMakeRect(p_to.x / displayScale, contentRect.size.height - (p_to.y / displayScale) - 1, 0, 0);
+ const float scale = screen_get_max_scale();
+ NSRect pointInWindowRect = NSMakeRect(p_to.x / scale, contentRect.size.height - (p_to.y / scale - 1), 0, 0);
NSPoint pointOnScreen = [[wd.window_view window] convertRectToScreen:pointInWindowRect].origin;
//point in scren coords
@@ -1942,7 +2083,9 @@ void DisplayServerOSX::mouse_warp_to_position(const Point2i &p_to) {
CGEventSourceSetLocalEventsSuppressionInterval(lEventRef, 0.0);
CGAssociateMouseAndMouseCursorPosition(false);
CGWarpMouseCursorPosition(lMouseWarpPos);
- CGAssociateMouseAndMouseCursorPosition(true);
+ if (mouse_mode != MOUSE_MODE_CONFINED) {
+ CGAssociateMouseAndMouseCursorPosition(true);
+ }
}
}
@@ -1954,11 +2097,12 @@ Point2i DisplayServerOSX::mouse_get_absolute_position() const {
_THREAD_SAFE_METHOD_
const NSPoint mouse_pos = [NSEvent mouseLocation];
+ const float scale = screen_get_max_scale();
for (NSScreen *screen in [NSScreen screens]) {
NSRect frame = [screen frame];
if (NSMouseInRect(mouse_pos, frame, NO)) {
- return Vector2i((int)mouse_pos.x, (int)-mouse_pos.y) + _get_screens_origin();
+ return Vector2i((int)mouse_pos.x, (int)-mouse_pos.y) * scale + _get_screens_origin();
}
}
return Vector2i();
@@ -2016,17 +2160,10 @@ int DisplayServerOSX::get_screen_count() const {
// to convert between OS X native screen coordinates and the ones expected by Godot
static bool displays_arrangement_dirty = true;
+static bool displays_scale_dirty = true;
static void displays_arrangement_changed(CGDirectDisplayID display_id, CGDisplayChangeSummaryFlags flags, void *user_info) {
displays_arrangement_dirty = true;
-}
-
-float DisplayServerOSX::_display_scale(id screen) const {
- if (OS_OSX::get_singleton()->is_hidpi_allowed()) {
- if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
- return fmax(1.0, [screen backingScaleFactor]);
- }
- }
- return 1.0;
+ displays_scale_dirty = true;
}
Point2i DisplayServerOSX::_get_screens_origin() const {
@@ -2053,10 +2190,9 @@ Point2i DisplayServerOSX::_get_screens_origin() const {
Point2i DisplayServerOSX::_get_native_screen_position(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if ((NSUInteger)p_screen < [screenArray count]) {
- float display_scale = _display_scale([screenArray objectAtIndex:p_screen]);
NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame];
// Return the top-left corner of the screen, for OS X the y starts at the bottom
- return Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * display_scale;
+ return Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * screen_get_max_scale();
}
return Point2i();
@@ -2085,10 +2221,9 @@ Size2i DisplayServerOSX::screen_get_size(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if ((NSUInteger)p_screen < [screenArray count]) {
- float displayScale = _display_scale([screenArray objectAtIndex:p_screen]);
// Note: Use frame to get the whole screen size
NSRect nsrect = [[screenArray objectAtIndex:p_screen] frame];
- return Size2i(nsrect.size.width, nsrect.size.height) * displayScale;
+ return Size2i(nsrect.size.width, nsrect.size.height) * screen_get_max_scale();
}
return Size2i();
@@ -2103,13 +2238,9 @@ int DisplayServerOSX::screen_get_dpi(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if ((NSUInteger)p_screen < [screenArray count]) {
- float displayScale = _display_scale([screenArray objectAtIndex:p_screen]);
NSDictionary *description = [[screenArray objectAtIndex:p_screen] deviceDescription];
- NSSize displayPixelSize = [[description objectForKey:NSDeviceSize] sizeValue];
- CGSize displayPhysicalSize = CGDisplayScreenSize(
- [[description objectForKey:@"NSScreenNumber"] unsignedIntValue]);
-
- return (displayPixelSize.width * 25.4f / displayPhysicalSize.width) * displayScale;
+ NSSize displayDPI = [[description objectForKey:NSDeviceResolution] sizeValue];
+ return (displayDPI.width + displayDPI.height) / 2;
}
return 96;
@@ -2121,14 +2252,32 @@ float DisplayServerOSX::screen_get_scale(int p_screen) const {
if (p_screen == SCREEN_OF_MAIN_WINDOW) {
p_screen = window_get_current_screen();
}
- NSArray *screenArray = [NSScreen screens];
- if ((NSUInteger)p_screen < [screenArray count]) {
- return _display_scale([screenArray objectAtIndex:p_screen]);
+ if (OS::get_singleton()->is_hidpi_allowed()) {
+ NSArray *screenArray = [NSScreen screens];
+ if ((NSUInteger)p_screen < [screenArray count]) {
+ if ([[screenArray objectAtIndex:p_screen] respondsToSelector:@selector(backingScaleFactor)]) {
+ return fmax(1.0, [[screenArray objectAtIndex:p_screen] backingScaleFactor]);
+ }
+ }
}
return 1.f;
}
+float DisplayServerOSX::screen_get_max_scale() const {
+ _THREAD_SAFE_METHOD_
+
+ static float scale = 1.f;
+ if (displays_scale_dirty) {
+ int screen_count = get_screen_count();
+ for (int i = 0; i < screen_count; i++) {
+ scale = fmax(scale, screen_get_scale(i));
+ }
+ displays_scale_dirty = false;
+ }
+ return scale;
+}
+
Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const {
_THREAD_SAFE_METHOD_
@@ -2138,12 +2287,12 @@ Rect2i DisplayServerOSX::screen_get_usable_rect(int p_screen) const {
NSArray *screenArray = [NSScreen screens];
if ((NSUInteger)p_screen < [screenArray count]) {
- float displayScale = _display_scale([screenArray objectAtIndex:p_screen]);
+ const float scale = screen_get_max_scale();
NSRect nsrect = [[screenArray objectAtIndex:p_screen] visibleFrame];
- Point2i position = Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * displayScale - _get_screens_origin();
+ Point2i position = Point2i(nsrect.origin.x, nsrect.origin.y + nsrect.size.height) * scale - _get_screens_origin();
position.y *= -1;
- Size2i size = Size2i(nsrect.size.width, nsrect.size.height) / displayScale;
+ Size2i size = Size2i(nsrect.size.width, nsrect.size.height) * scale;
return Rect2i(position, size);
}
@@ -2165,16 +2314,25 @@ DisplayServer::WindowID DisplayServerOSX::create_sub_window(WindowMode p_mode, u
_THREAD_SAFE_METHOD_
WindowID id = _create_window(p_mode, p_rect);
- WindowData &wd = windows[id];
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, id);
}
}
- [wd.window_object makeKeyAndOrderFront:nil];
+
return id;
}
+void DisplayServerOSX::show_window(WindowID p_id) {
+ WindowData &wd = windows[p_id];
+
+ if (wd.no_focus) {
+ [wd.window_object orderFront:nil];
+ } else {
+ [wd.window_object makeKeyAndOrderFront:nil];
+ }
+}
+
void DisplayServerOSX::_send_window_event(const WindowData &wd, WindowEvent p_event) {
_THREAD_SAFE_METHOD_
@@ -2189,8 +2347,9 @@ void DisplayServerOSX::_send_window_event(const WindowData &wd, WindowEvent p_ev
DisplayServerOSX::WindowID DisplayServerOSX::_find_window_id(id p_window) {
for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- if (E->get().window_object == p_window)
+ if (E->get().window_object == p_window) {
return E->key();
+ }
}
return INVALID_WINDOW_ID;
}
@@ -2314,7 +2473,7 @@ void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent
wd_window.transient_parent = INVALID_WINDOW_ID;
wd_parent.transient_children.erase(p_window);
- [wd_window.window_object setParentWindow:nil];
+ [wd_parent.window_object removeChildWindow:wd_window.window_object];
} else {
ERR_FAIL_COND(!windows.has(p_parent));
ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent");
@@ -2323,7 +2482,7 @@ void DisplayServerOSX::window_set_transient(WindowID p_window, WindowID p_parent
wd_window.transient_parent = p_parent;
wd_parent.transient_children.insert(p_window);
- [wd_window.window_object setParentWindow:wd_parent.window_object];
+ [wd_parent.window_object addChildWindow:wd_window.window_object ordered:NSWindowAbove];
}
}
@@ -2335,11 +2494,12 @@ Point2i DisplayServerOSX::window_get_position(WindowID p_window) const {
NSRect nsrect = [wd.window_object frame];
Point2i pos;
- float display_scale = _display_scale([wd.window_object screen]);
// Return the position of the top-left corner, for OS X the y starts at the bottom
- pos.x = nsrect.origin.x * display_scale;
- pos.y = (nsrect.origin.y + nsrect.size.height) * display_scale;
+ const float scale = screen_get_max_scale();
+ pos.x = nsrect.origin.x;
+ pos.y = (nsrect.origin.y + nsrect.size.height);
+ pos *= scale;
pos -= _get_screens_origin();
// OS X native y-coordinate relative to _get_screens_origin() is negative,
// Godot expects a positive value
@@ -2358,17 +2518,12 @@ void DisplayServerOSX::window_set_position(const Point2i &p_position, WindowID p
// Godot passes a positive value
position.y *= -1;
position += _get_screens_origin();
+ position /= screen_get_max_scale();
- NSPoint pos;
- float displayScale = _display_scale([wd.window_object screen]);
-
- pos.x = position.x / displayScale;
- pos.y = position.y / displayScale;
-
- [wd.window_object setFrameTopLeftPoint:pos];
+ [wd.window_object setFrameTopLeftPoint:NSMakePoint(position.x, position.y)];
_update_window(wd);
- _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream], displayScale);
+ _get_mouse_pos(wd, [wd.window_object mouseLocationOutsideOfEventStream]);
}
void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_window) {
@@ -2384,7 +2539,7 @@ void DisplayServerOSX::window_set_max_size(const Size2i p_size, WindowID p_windo
wd.max_size = p_size;
if ((wd.max_size != Size2i()) && !wd.fullscreen) {
- Size2i size = wd.max_size / _display_scale([wd.window_object screen]);
+ Size2i size = wd.max_size / screen_get_max_scale();
[wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)];
} else {
[wd.window_object setContentMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
@@ -2412,7 +2567,7 @@ void DisplayServerOSX::window_set_min_size(const Size2i p_size, WindowID p_windo
wd.min_size = p_size;
if ((wd.min_size != Size2i()) && !wd.fullscreen) {
- Size2i size = wd.min_size / _display_scale([wd.window_object screen]);
+ Size2i size = wd.min_size / screen_get_max_scale();
[wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)];
} else {
[wd.window_object setContentMinSize:NSMakeSize(0, 0)];
@@ -2434,18 +2589,20 @@ void DisplayServerOSX::window_set_size(const Size2i p_size, WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- Size2i size = p_size / _display_scale([wd.window_object screen]);
+ Size2i size = p_size / screen_get_max_scale();
- if (!wd.borderless) {
- // NSRect used by setFrame includes the title bar, so add it to our size.y
- CGFloat menuBarHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight];
- if (menuBarHeight != 0.f) {
- size.y += menuBarHeight;
- }
- }
+ NSPoint top_left;
+ NSRect old_frame = [wd.window_object frame];
+ top_left.x = old_frame.origin.x;
+ top_left.y = NSMaxY(old_frame);
- NSRect frame = [wd.window_object frame];
- [wd.window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, size.x, size.y) display:YES];
+ NSRect new_frame = NSMakeRect(0, 0, size.x, size.y);
+ new_frame = [wd.window_object frameRectForContentRect:new_frame];
+
+ new_frame.origin.x = top_left.x;
+ new_frame.origin.y = top_left.y - new_frame.size.height;
+
+ [wd.window_object setFrame:new_frame display:YES];
_update_window(wd);
}
@@ -2464,7 +2621,7 @@ Size2i DisplayServerOSX::window_get_real_size(WindowID p_window) const {
ERR_FAIL_COND_V(!windows.has(p_window), Size2i());
const WindowData &wd = windows[p_window];
NSRect frame = [wd.window_object frame];
- return Size2i(frame.size.width, frame.size.height) * _display_scale([wd.window_object screen]);
+ return Size2i(frame.size.width, frame.size.height) * screen_get_max_scale();
}
bool DisplayServerOSX::window_is_maximize_allowed(WindowID p_window) const {
@@ -2475,23 +2632,26 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- if (!OS_OSX::get_singleton()->is_layered_allowed()) return;
+ if (!OS_OSX::get_singleton()->is_layered_allowed()) {
+ return;
+ }
if (wd.layered_window != p_enabled) {
if (p_enabled) {
[wd.window_object setBackgroundColor:[NSColor clearColor]];
[wd.window_object setOpaque:NO];
[wd.window_object setHasShadow:NO];
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ [layer setOpaque:NO];
+ }
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- [layer setOpaque:NO];
//TODO - implement transparency for Vulkan
}
#endif
#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2->set_opacity(0);
}
#endif
wd.layered_window = true;
@@ -2499,17 +2659,18 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
[wd.window_object setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1]];
[wd.window_object setOpaque:YES];
[wd.window_object setHasShadow:YES];
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ [layer setOpaque:YES];
+ }
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- [layer setOpaque:YES];
//TODO - implement transparency for Vulkan
}
#endif
#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2->set_opacity(1);
}
#endif
wd.layered_window = false;
@@ -2517,7 +2678,11 @@ void DisplayServerOSX::_set_window_per_pixel_transparency_enabled(bool p_enabled
#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2->update();
+ }
+#endif
+#if defined(VULKAN_ENABLED)
+ if (rendering_driver == "vulkan") {
+ //TODO - implement transparency for Vulkan
}
#endif
NSRect frameRect = [wd.window_object frame];
@@ -2545,16 +2710,18 @@ void DisplayServerOSX::window_set_mode(WindowMode p_mode, WindowID p_window) {
[wd.window_object deminiaturize:nil];
} break;
case WINDOW_MODE_FULLSCREEN: {
- if (wd.layered_window)
+ if (wd.layered_window) {
_set_window_per_pixel_transparency_enabled(true, p_window);
- if (wd.resize_disabled) //restore resize disabled
+ }
+ if (wd.resize_disabled) { //restore resize disabled
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
+ }
if (wd.min_size != Size2i()) {
- Size2i size = wd.min_size / _display_scale([wd.window_object screen]);
+ Size2i size = wd.min_size / screen_get_max_scale();
[wd.window_object setContentMinSize:NSMakeSize(size.x, size.y)];
}
if (wd.max_size != Size2i()) {
- Size2i size = wd.max_size / _display_scale([wd.window_object screen]);
+ Size2i size = wd.max_size / screen_get_max_scale();
[wd.window_object setContentMaxSize:NSMakeSize(size.x, size.y)];
}
[wd.window_object toggleFullScreen:nil];
@@ -2623,8 +2790,9 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
switch (p_flag) {
case WINDOW_FLAG_RESIZE_DISABLED: {
wd.resize_disabled = p_enabled;
- if (wd.fullscreen) //fullscreen window should be resizable, style will be applyed on exiting fs
+ if (wd.fullscreen) { //fullscreen window should be resizable, style will be applied on exiting fs
return;
+ }
if (p_enabled) {
[wd.window_object setStyleMask:[wd.window_object styleMask] & ~NSWindowStyleMaskResizable];
} else {
@@ -2633,7 +2801,9 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
} break;
case WINDOW_FLAG_BORDERLESS: {
// OrderOut prevents a lose focus bug with the window
- [wd.window_object orderOut:nil];
+ if ([wd.window_object isVisible]) {
+ [wd.window_object orderOut:nil];
+ }
wd.borderless = p_enabled;
if (p_enabled) {
[wd.window_object setStyleMask:NSWindowStyleMaskBorderless];
@@ -2647,7 +2817,13 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
[wd.window_object setFrame:frameRect display:NO];
}
_update_window(wd);
- [wd.window_object makeKeyAndOrderFront:nil];
+ if ([wd.window_object isVisible]) {
+ if (wd.no_focus) {
+ [wd.window_object orderFront:nil];
+ } else {
+ [wd.window_object makeKeyAndOrderFront:nil];
+ }
+ }
} break;
case WINDOW_FLAG_ALWAYS_ON_TOP: {
wd.on_top = p_enabled;
@@ -2665,7 +2841,9 @@ void DisplayServerOSX::window_set_flag(WindowFlags p_flag, bool p_enabled, Windo
[wd.window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | (wd.resize_disabled ? 0 : NSWindowStyleMaskResizable)];
}
_set_window_per_pixel_transparency_enabled(p_enabled, p_window);
-
+ } break;
+ case WINDOW_FLAG_NO_FOCUS: {
+ wd.no_focus = p_enabled;
} break;
default: {
}
@@ -2691,6 +2869,9 @@ bool DisplayServerOSX::window_get_flag(WindowFlags p_flag, WindowID p_window) co
case WINDOW_FLAG_TRANSPARENT: {
return wd.layered_window;
} break;
+ case WINDOW_FLAG_NO_FOCUS: {
+ return wd.no_focus;
+ } break;
default: {
}
}
@@ -2710,7 +2891,11 @@ void DisplayServerOSX::window_move_to_foreground(WindowID p_window) {
const WindowData &wd = windows[p_window];
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
- [wd.window_object makeKeyAndOrderFront:nil];
+ if (wd.no_focus) {
+ [wd.window_object orderFront:nil];
+ } else {
+ [wd.window_object makeKeyAndOrderFront:nil];
+ }
}
bool DisplayServerOSX::window_can_draw(WindowID p_window) const {
@@ -2736,8 +2921,9 @@ void DisplayServerOSX::window_set_ime_active(const bool p_active, WindowID p_win
wd.im_active = p_active;
- if (!p_active)
+ if (!p_active) {
[wd.window_view cancelComposition];
+ }
}
void DisplayServerOSX::window_set_ime_position(const Point2i &p_pos, WindowID p_window) {
@@ -2749,8 +2935,8 @@ void DisplayServerOSX::window_set_ime_position(const Point2i &p_pos, WindowID p_
wd.im_position = p_pos;
}
-bool DisplayServerOSX::get_swap_ok_cancel() {
- return true;
+bool DisplayServerOSX::get_swap_cancel_ok() {
+ return false;
}
void DisplayServerOSX::cursor_set_shape(CursorShape p_shape) {
@@ -2758,8 +2944,9 @@ void DisplayServerOSX::cursor_set_shape(CursorShape p_shape) {
ERR_FAIL_INDEX(p_shape, CURSOR_MAX);
- if (cursor_shape == p_shape)
+ if (cursor_shape == p_shape) {
return;
+ }
if (mouse_mode != MOUSE_MODE_VISIBLE && mouse_mode != MOUSE_MODE_CONFINED) {
cursor_shape = p_shape;
@@ -2770,23 +2957,57 @@ void DisplayServerOSX::cursor_set_shape(CursorShape p_shape) {
[cursors[p_shape] set];
} else {
switch (p_shape) {
- case CURSOR_ARROW: [[NSCursor arrowCursor] set]; break;
- case CURSOR_IBEAM: [[NSCursor IBeamCursor] set]; break;
- case CURSOR_POINTING_HAND: [[NSCursor pointingHandCursor] set]; break;
- case CURSOR_CROSS: [[NSCursor crosshairCursor] set]; break;
- case CURSOR_WAIT: [[NSCursor arrowCursor] set]; break;
- case CURSOR_BUSY: [[NSCursor arrowCursor] set]; break;
- case CURSOR_DRAG: [[NSCursor closedHandCursor] set]; break;
- case CURSOR_CAN_DROP: [[NSCursor openHandCursor] set]; break;
- case CURSOR_FORBIDDEN: [[NSCursor operationNotAllowedCursor] set]; break;
- case CURSOR_VSIZE: [_cursorFromSelector(@selector(_windowResizeNorthSouthCursor), @selector(resizeUpDownCursor)) set]; break;
- case CURSOR_HSIZE: [_cursorFromSelector(@selector(_windowResizeEastWestCursor), @selector(resizeLeftRightCursor)) set]; break;
- case CURSOR_BDIAGSIZE: [_cursorFromSelector(@selector(_windowResizeNorthEastSouthWestCursor)) set]; break;
- case CURSOR_FDIAGSIZE: [_cursorFromSelector(@selector(_windowResizeNorthWestSouthEastCursor)) set]; break;
- case CURSOR_MOVE: [[NSCursor arrowCursor] set]; break;
- case CURSOR_VSPLIT: [[NSCursor resizeUpDownCursor] set]; break;
- case CURSOR_HSPLIT: [[NSCursor resizeLeftRightCursor] set]; break;
- case CURSOR_HELP: [_cursorFromSelector(@selector(_helpCursor)) set]; break;
+ case CURSOR_ARROW:
+ [[NSCursor arrowCursor] set];
+ break;
+ case CURSOR_IBEAM:
+ [[NSCursor IBeamCursor] set];
+ break;
+ case CURSOR_POINTING_HAND:
+ [[NSCursor pointingHandCursor] set];
+ break;
+ case CURSOR_CROSS:
+ [[NSCursor crosshairCursor] set];
+ break;
+ case CURSOR_WAIT:
+ [[NSCursor arrowCursor] set];
+ break;
+ case CURSOR_BUSY:
+ [[NSCursor arrowCursor] set];
+ break;
+ case CURSOR_DRAG:
+ [[NSCursor closedHandCursor] set];
+ break;
+ case CURSOR_CAN_DROP:
+ [[NSCursor openHandCursor] set];
+ break;
+ case CURSOR_FORBIDDEN:
+ [[NSCursor operationNotAllowedCursor] set];
+ break;
+ case CURSOR_VSIZE:
+ [_cursorFromSelector(@selector(_windowResizeNorthSouthCursor), @selector(resizeUpDownCursor)) set];
+ break;
+ case CURSOR_HSIZE:
+ [_cursorFromSelector(@selector(_windowResizeEastWestCursor), @selector(resizeLeftRightCursor)) set];
+ break;
+ case CURSOR_BDIAGSIZE:
+ [_cursorFromSelector(@selector(_windowResizeNorthEastSouthWestCursor)) set];
+ break;
+ case CURSOR_FDIAGSIZE:
+ [_cursorFromSelector(@selector(_windowResizeNorthWestSouthEastCursor)) set];
+ break;
+ case CURSOR_MOVE:
+ [[NSCursor arrowCursor] set];
+ break;
+ case CURSOR_VSPLIT:
+ [[NSCursor resizeUpDownCursor] set];
+ break;
+ case CURSOR_HSPLIT:
+ [[NSCursor resizeLeftRightCursor] set];
+ break;
+ case CURSOR_HELP:
+ [_cursorFromSelector(@selector(_helpCursor)) set];
+ break;
default: {
}
}
@@ -2918,97 +3139,140 @@ void DisplayServerOSX::cursor_set_custom_image(const RES &p_cursor, CursorShape
}
}
+struct LayoutInfo {
+ String name;
+ String code;
+};
+
+static Vector<LayoutInfo> kbd_layouts;
+static int current_layout = 0;
static bool keyboard_layout_dirty = true;
static void keyboard_layout_changed(CFNotificationCenterRef center, void *observer, CFStringRef name, const void *object, CFDictionaryRef user_info) {
+ kbd_layouts.clear();
+ current_layout = 0;
keyboard_layout_dirty = true;
}
-// Returns string representation of keys, if they are printable.
-static NSString *createStringForKeys(const CGKeyCode *keyCode, int length) {
- TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
- if (!currentKeyboard)
- return nil;
+void _update_keyboard_layouts() {
+ @autoreleasepool {
+ TISInputSourceRef cur_source = TISCopyCurrentKeyboardInputSource();
+ NSString *cur_name = (NSString *)TISGetInputSourceProperty(cur_source, kTISPropertyLocalizedName);
+ CFRelease(cur_source);
- CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
- if (!layoutData)
- return nil;
+ // Enum IME layouts
+ NSDictionary *filter_ime = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardInputMode };
+ NSArray *list_ime = (NSArray *)TISCreateInputSourceList((CFDictionaryRef)filter_ime, false);
+ for (NSUInteger i = 0; i < [list_ime count]; i++) {
+ LayoutInfo ly;
+ NSString *name = (NSString *)TISGetInputSourceProperty((TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyLocalizedName);
+ ly.name.parse_utf8([name UTF8String]);
- const UCKeyboardLayout *keyboardLayout = (const UCKeyboardLayout *)CFDataGetBytePtr(layoutData);
+ NSArray *langs = (NSArray *)TISGetInputSourceProperty((TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyInputSourceLanguages);
+ ly.code.parse_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]);
+ kbd_layouts.push_back(ly);
- OSStatus err;
- CFMutableStringRef output = CFStringCreateMutable(NULL, 0);
+ if ([name isEqualToString:cur_name]) {
+ current_layout = kbd_layouts.size() - 1;
+ }
+ }
+ [list_ime release];
- for (int i = 0; i < length; ++i) {
- UInt32 keysDown = 0;
- UniChar chars[4];
- UniCharCount realLength;
+ // Enum plain keyboard layouts
+ NSDictionary *filter_kbd = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardLayout };
+ NSArray *list_kbd = (NSArray *)TISCreateInputSourceList((CFDictionaryRef)filter_kbd, false);
+ for (NSUInteger i = 0; i < [list_kbd count]; i++) {
+ LayoutInfo ly;
+ NSString *name = (NSString *)TISGetInputSourceProperty((TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyLocalizedName);
+ ly.name.parse_utf8([name UTF8String]);
- err = UCKeyTranslate(keyboardLayout,
- keyCode[i],
- kUCKeyActionDisplay,
- 0,
- LMGetKbdType(),
- kUCKeyTranslateNoDeadKeysBit,
- &keysDown,
- sizeof(chars) / sizeof(chars[0]),
- &realLength,
- chars);
+ NSArray *langs = (NSArray *)TISGetInputSourceProperty((TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyInputSourceLanguages);
+ ly.code.parse_utf8([(NSString *)[langs objectAtIndex:0] UTF8String]);
+ kbd_layouts.push_back(ly);
- if (err != noErr) {
- CFRelease(output);
- return nil;
+ if ([name isEqualToString:cur_name]) {
+ current_layout = kbd_layouts.size() - 1;
+ }
}
-
- CFStringAppendCharacters(output, chars, 1);
+ [list_kbd release];
}
- return (NSString *)output;
+ keyboard_layout_dirty = false;
}
-DisplayServerOSX::LatinKeyboardVariant DisplayServerOSX::get_latin_keyboard_variant() const {
- _THREAD_SAFE_METHOD_
-
- static LatinKeyboardVariant layout = LATIN_KEYBOARD_QWERTY;
+int DisplayServerOSX::keyboard_get_layout_count() const {
+ if (keyboard_layout_dirty) {
+ _update_keyboard_layouts();
+ }
+ return kbd_layouts.size();
+}
+void DisplayServerOSX::keyboard_set_current_layout(int p_index) {
if (keyboard_layout_dirty) {
+ _update_keyboard_layouts();
+ }
- layout = LATIN_KEYBOARD_QWERTY;
+ ERR_FAIL_INDEX(p_index, kbd_layouts.size());
- CGKeyCode keys[] = { kVK_ANSI_Q, kVK_ANSI_W, kVK_ANSI_E, kVK_ANSI_R, kVK_ANSI_T, kVK_ANSI_Y };
- NSString *test = createStringForKeys(keys, 6);
+ NSString *cur_name = [NSString stringWithUTF8String:kbd_layouts[p_index].name.utf8().get_data()];
- if ([test isEqualToString:@"qwertz"]) {
- layout = LATIN_KEYBOARD_QWERTZ;
- } else if ([test isEqualToString:@"azerty"]) {
- layout = LATIN_KEYBOARD_AZERTY;
- } else if ([test isEqualToString:@"qzerty"]) {
- layout = LATIN_KEYBOARD_QZERTY;
- } else if ([test isEqualToString:@"',.pyf"]) {
- layout = LATIN_KEYBOARD_DVORAK;
- } else if ([test isEqualToString:@"xvlcwk"]) {
- layout = LATIN_KEYBOARD_NEO;
- } else if ([test isEqualToString:@"qwfpgj"]) {
- layout = LATIN_KEYBOARD_COLEMAK;
+ NSDictionary *filter_kbd = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardLayout };
+ NSArray *list_kbd = (NSArray *)TISCreateInputSourceList((CFDictionaryRef)filter_kbd, false);
+ for (NSUInteger i = 0; i < [list_kbd count]; i++) {
+ NSString *name = (NSString *)TISGetInputSourceProperty((TISInputSourceRef)[list_kbd objectAtIndex:i], kTISPropertyLocalizedName);
+ if ([name isEqualToString:cur_name]) {
+ TISSelectInputSource((TISInputSourceRef)[list_kbd objectAtIndex:i]);
+ break;
}
+ }
+ [list_kbd release];
- [test release];
+ NSDictionary *filter_ime = @{ (NSString *)kTISPropertyInputSourceType : (NSString *)kTISTypeKeyboardInputMode };
+ NSArray *list_ime = (NSArray *)TISCreateInputSourceList((CFDictionaryRef)filter_ime, false);
+ for (NSUInteger i = 0; i < [list_ime count]; i++) {
+ NSString *name = (NSString *)TISGetInputSourceProperty((TISInputSourceRef)[list_ime objectAtIndex:i], kTISPropertyLocalizedName);
+ if ([name isEqualToString:cur_name]) {
+ TISSelectInputSource((TISInputSourceRef)[list_ime objectAtIndex:i]);
+ break;
+ }
+ }
+ [list_ime release];
+}
- keyboard_layout_dirty = false;
- return layout;
+int DisplayServerOSX::keyboard_get_current_layout() const {
+ if (keyboard_layout_dirty) {
+ _update_keyboard_layouts();
}
- return layout;
+ return current_layout;
+}
+
+String DisplayServerOSX::keyboard_get_layout_language(int p_index) const {
+ if (keyboard_layout_dirty) {
+ _update_keyboard_layouts();
+ }
+
+ ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), "");
+ return kbd_layouts[p_index].code;
+}
+
+String DisplayServerOSX::keyboard_get_layout_name(int p_index) const {
+ if (keyboard_layout_dirty) {
+ _update_keyboard_layouts();
+ }
+
+ ERR_FAIL_INDEX_V(p_index, kbd_layouts.size(), "");
+ return kbd_layouts[p_index].name;
}
void DisplayServerOSX::_push_input(const Ref<InputEvent> &p_event) {
Ref<InputEvent> ev = p_event;
- InputFilter::get_singleton()->accumulate_input_event(ev);
+ Input::get_singleton()->accumulate_input_event(ev);
}
void DisplayServerOSX::_release_pressed_events() {
_THREAD_SAFE_METHOD_
- if (InputFilter::get_singleton()) {
- InputFilter::get_singleton()->release_pressed_events();
+ if (Input::get_singleton()) {
+ Input::get_singleton()->release_pressed_events();
}
}
@@ -3076,15 +3340,16 @@ void DisplayServerOSX::process_events() {
inMode:NSDefaultRunLoopMode
dequeue:YES];
- if (event == nil)
+ if (event == nil) {
break;
+ }
[NSApp sendEvent:event];
}
if (!drop_events) {
_process_key_events();
- InputFilter::get_singleton()->flush_accumulated_events();
+ Input::get_singleton()->flush_accumulated_events();
}
[autoreleasePool drain];
@@ -3165,11 +3430,11 @@ void DisplayServerOSX::set_icon(const Ref<Image> &p_icon) {
Vector<String> DisplayServerOSX::get_rendering_drivers_func() {
Vector<String> drivers;
-#ifdef VULKAN_ENABLED
+#if defined(VULKAN_ENABLED)
drivers.push_back("vulkan");
#endif
-#ifdef OPENGL_ENABLED
- drivers.push_back("opengl");
+#if defined(OPENGL_ENABLED)
+ drivers.push_back("opengl_es");
#endif
return drivers;
@@ -3184,9 +3449,14 @@ String DisplayServerOSX::ime_get_text() const {
}
DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Point2i &p_position) const {
+ Point2i position = p_position;
+ position.y *= -1;
+ position += _get_screens_origin();
+ position /= screen_get_max_scale();
+
+ NSInteger wnum = [NSWindow windowNumberAtPoint:NSMakePoint(position.x, position.y) belowWindowWithWindowNumber:0 /*topmost*/];
for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) {
- Rect2i win_rect = Rect2i(window_get_position(E->key()), window_get_size(E->key()));
- if (win_rect.has_point(p_position)) {
+ if ([E->get().window_object windowNumber] == wnum) {
return E->key();
}
}
@@ -3208,23 +3478,19 @@ ObjectID DisplayServerOSX::window_get_attached_instance_id(WindowID p_window) co
}
DisplayServer *DisplayServerOSX::create_func(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- return memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+ DisplayServer *ds = memnew(DisplayServerOSX(p_rendering_driver, p_mode, p_flags, p_resolution, r_error));
+ if (r_error != OK) {
+ ds->alert("Your video card driver does not support any of the supported Metal versions.", "Unable to initialize Video driver");
+ }
+ return ds;
}
DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, const Rect2i &p_rect) {
WindowID id;
+ const float scale = screen_get_max_scale();
{
WindowData wd;
- float displayScale = 1.0;
- if (OS_OSX::get_singleton()->is_hidpi_allowed()) {
- // note that mainScreen is not screen #0 but the one with the keyboard focus.
- NSScreen *screen = [NSScreen mainScreen];
- if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
- displayScale = fmax(displayScale, [screen backingScaleFactor]);
- }
- }
-
wd.window_delegate = [[GodotWindowDelegate alloc] init];
ERR_FAIL_COND_V_MSG(wd.window_delegate == nil, INVALID_WINDOW_ID, "Can't create a window delegate");
[wd.window_delegate setWindowID:window_id_counter];
@@ -3237,7 +3503,7 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, c
// initWithContentRect uses bottom-left corner of the window’s frame as origin.
wd.window_object = [[GodotWindow alloc]
- initWithContentRect:NSMakeRect(position.x / displayScale, (position.y - p_rect.size.height) / displayScale, p_rect.size.width / displayScale, p_rect.size.height / displayScale)
+ initWithContentRect:NSMakeRect(position.x / scale, (position.y - p_rect.size.height) / scale, p_rect.size.width / scale, p_rect.size.height / scale)
styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable
backing:NSBackingStoreBuffered
defer:NO];
@@ -3246,24 +3512,7 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, c
wd.window_view = [[GodotContentView alloc] init];
ERR_FAIL_COND_V_MSG(wd.window_view == nil, INVALID_WINDOW_ID, "Can't create a window view");
[wd.window_view setWindowID:window_id_counter];
- if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_14) {
- [wd.window_view setWantsLayer:TRUE];
- }
-
- if (displayScale > 1.0) {
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
- [wd.window_view setWantsBestResolutionOpenGLSurface:YES];
- }
-#endif
- [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
- } else {
-#if defined(OPENGL_ENABLED)
- if (rendering_driver == "opengl_es") {
- [wd.window_view setWantsBestResolutionOpenGLSurface:NO];
- }
-#endif
- }
+ [wd.window_view setWantsLayer:TRUE];
[wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
[wd.window_object setContentView:wd.window_view];
@@ -3271,33 +3520,26 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, c
[wd.window_object setAcceptsMouseMovedEvents:YES];
[wd.window_object setRestorable:NO];
- if ([wd.window_object respondsToSelector:@selector(setTabbingMode:)])
+ if ([wd.window_object respondsToSelector:@selector(setTabbingMode:)]) {
[wd.window_object setTabbingMode:NSWindowTabbingModeDisallowed];
+ }
+
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ layer.contentsScale = scale;
+ }
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
if (context_vulkan) {
- CALayer *layer = [wd.window_view layer];
- layer.contentsScale = displayScale;
Error err = context_vulkan->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 a Vulkan context");
}
}
#endif
-#ifdef OPENGL_ENABLED
+#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
//TODO - reimplement OpenGLES
- wd.context_gles2 = memnew(ContextGL_OSX(wd.window_view, false));
-
- if (wd.context_gles2->initialize() != OK) {
- memdelete(wd.context_gles2);
- ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create a OpenGL context");
- }
-
- //if (RasterizerGLES2::is_viable() == OK) {
- // RasterizerGLES2::register_config();
- // RasterizerGLES2::make_current();
- //}
}
#endif
id = window_id_counter++;
@@ -3307,25 +3549,22 @@ DisplayServerOSX::WindowID DisplayServerOSX::_create_window(WindowMode p_mode, c
WindowData &wd = windows[id];
window_set_mode(p_mode, id);
- float displayScale = _display_scale([wd.window_object screen]);
const NSRect contentRect = [wd.window_view frame];
- wd.size.width = contentRect.size.width * displayScale;
- wd.size.height = contentRect.size.height * displayScale;
+ wd.size.width = contentRect.size.width * scale;
+ wd.size.height = contentRect.size.height * scale;
+
+ CALayer *layer = [wd.window_view layer];
+ if (layer) {
+ layer.contentsScale = scale;
+ }
#if defined(OPENGL_ENABLED)
if (rendering_driver == "opengl_es") {
- if (OS_OSX::singleton->is_hidpi_allowed()) {
- [wd.window_view setWantsBestResolutionOpenGLSurface:YES];
- } else {
- [wd.window_view setWantsBestResolutionOpenGLSurface:NO];
- }
- wd.context_gles2->update();
+ //TODO - reimplement OpenGLES
}
#endif
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
- CALayer *layer = [wd.window_view layer];
- layer.contentsScale = displayScale;
context_vulkan->window_resize(id, wd.size.width, wd.size.height);
}
#endif
@@ -3393,7 +3632,7 @@ bool DisplayServerOSX::is_console_visible() const {
}
DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode p_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) {
- InputFilter::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
+ Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events);
r_error = OK;
drop_events = false;
@@ -3420,6 +3659,7 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
keyboard_layout_dirty = true;
displays_arrangement_dirty = true;
+ displays_scale_dirty = true;
// Register to be notified on keyboard layout changes
CFNotificationCenterAddObserver(CFNotificationCenterGetDistributedCenter(),
@@ -3437,8 +3677,9 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
NSString *title;
NSString *nsappname = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"];
- if (nsappname == nil)
+ if (nsappname == nil) {
nsappname = [[NSProcessInfo processInfo] processName];
+ }
// Setup Dock menu
dock_menu = [[NSMenu alloc] initWithTitle:@"_dock"];
@@ -3491,8 +3732,9 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
inMode:NSDefaultRunLoopMode
dequeue:YES];
- if (event == nil)
+ if (event == nil) {
break;
+ }
[NSApp sendEvent:event];
}
@@ -3513,7 +3755,6 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
#endif
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
-
context_vulkan = memnew(VulkanContextOSX);
if (context_vulkan->initialize() != OK) {
memdelete(context_vulkan);
@@ -3524,14 +3765,23 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
}
#endif
- WindowID main_window = _create_window(p_mode, Rect2i(Point2i(), p_resolution));
+ Point2i window_position(
+ screen_get_position(0).x + (screen_get_size(0).width - p_resolution.width) / 2,
+ screen_get_position(0).y + (screen_get_size(0).height - p_resolution.height) / 2);
+ WindowID main_window = _create_window(p_mode, Rect2i(window_position, p_resolution));
+ ERR_FAIL_COND(main_window == INVALID_WINDOW_ID);
for (int i = 0; i < WINDOW_FLAG_MAX; i++) {
if (p_flags & (1 << i)) {
window_set_flag(WindowFlags(i), true, main_window);
}
}
- [windows[main_window].window_object makeKeyAndOrderFront:nil];
+ show_window(MAIN_WINDOW_ID);
+#if defined(OPENGL_ENABLED)
+ if (rendering_driver == "opengl_es") {
+ //TODO - reimplement OpenGLES
+ }
+#endif
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
rendering_device_vulkan = memnew(RenderingDeviceVulkan);
@@ -3542,14 +3792,6 @@ DisplayServerOSX::DisplayServerOSX(const String &p_rendering_driver, WindowMode
#endif
[NSApp activateIgnoringOtherApps:YES];
-
- /*
- 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));
- }
- visual_server->init();
- */
}
DisplayServerOSX::~DisplayServerOSX() {
@@ -3568,16 +3810,21 @@ DisplayServerOSX::~DisplayServerOSX() {
}
//destroy drivers
+#if defined(OPENGL_ENABLED)
+ if (rendering_driver == "opengl_es") {
+ //TODO - reimplement OpenGLES
+ }
+#endif
#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
-
if (rendering_device_vulkan) {
rendering_device_vulkan->finalize();
memdelete(rendering_device_vulkan);
}
- if (context_vulkan)
+ if (context_vulkan) {
memdelete(context_vulkan);
+ }
}
#endif
@@ -3585,9 +3832,6 @@ DisplayServerOSX::~DisplayServerOSX() {
CGDisplayRemoveReconfigurationCallback(displays_arrangement_changed, NULL);
cursors_cache.clear();
-
- //visual_server->finish();
- //memdelete(visual_server);
}
void DisplayServerOSX::register_osx_driver() {
diff --git a/platform/osx/export/export.cpp b/platform/osx/export/export.cpp
index c2df9c7082..0cf02ef69b 100644
--- a/platform/osx/export/export.cpp
+++ b/platform/osx/export/export.cpp
@@ -46,7 +46,6 @@
#include <sys/stat.h>
class EditorExportPlatformOSX : public EditorExportPlatform {
-
GDCLASS(EditorExportPlatformOSX, EditorExportPlatform);
int version_code;
@@ -56,8 +55,10 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
void _fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary);
void _make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data);
+ Error _notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path);
Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
Error _create_dmg(const String &p_dmg_path, const String &p_pkg_name, const String &p_app_path_name);
+ void _zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name);
#ifdef OSX_ENABLED
bool use_codesign() const { return true; }
@@ -66,17 +67,39 @@ class EditorExportPlatformOSX : public EditorExportPlatform {
bool use_codesign() const { return false; }
bool use_dmg() const { return false; }
#endif
+ bool is_package_name_valid(const String &p_package, String *r_error = nullptr) const {
+ String pname = p_package;
+
+ if (pname.length() == 0) {
+ if (r_error) {
+ *r_error = TTR("Identifier is missing.");
+ }
+ return false;
+ }
+
+ for (int i = 0; i < pname.length(); i++) {
+ CharType c = pname[i];
+ if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '-' || c == '.')) {
+ if (r_error) {
+ *r_error = vformat(TTR("The character '%s' is not allowed in Identifier."), String::chr(c));
+ }
+ return false;
+ }
+ }
+
+ return true;
+ }
protected:
- virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features);
- virtual void get_export_options(List<ExportOption> *r_options);
+ virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features) override;
+ virtual void get_export_options(List<ExportOption> *r_options) override;
public:
- virtual String get_name() const { return "Mac OSX"; }
- virtual String get_os_name() const { return "OSX"; }
- virtual Ref<Texture2D> get_logo() const { return logo; }
+ virtual String get_name() const override { return "macOS"; }
+ virtual String get_os_name() const override { return "macOS"; }
+ virtual Ref<Texture2D> get_logo() const override { return logo; }
- virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const {
+ virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override {
List<String> list;
if (use_dmg()) {
list.push_back("dmg");
@@ -84,18 +107,17 @@ public:
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;
+ virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
- virtual void get_platform_features(List<String> *r_features) {
+ virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override;
+ virtual void get_platform_features(List<String> *r_features) override {
r_features->push_back("pc");
r_features->push_back("s3tc");
r_features->push_back("OSX");
}
- virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) {
+ virtual void resolve_platform_feature_priorities(const Ref<EditorExportPreset> &p_preset, Set<String> &p_features) override {
}
EditorExportPlatformOSX();
@@ -117,14 +139,13 @@ void EditorExportPlatformOSX::get_preset_features(const Ref<EditorExportPreset>
}
void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options) {
-
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/debug", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "custom_template/release", PROPERTY_HINT_GLOBAL_FILE, "*.zip"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/info"), "Made with Godot Engine"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.png,*.icns"), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/bundle_identifier", PROPERTY_HINT_PLACEHOLDER_TEXT, "com.example.game"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/signature"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/short_version"), "1.0"));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/version"), "1.0"));
@@ -140,6 +161,11 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "codesign/hardened_runtime"), true));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "codesign/entitlements", PROPERTY_HINT_GLOBAL_FILE, "*.plist"), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
+
+ r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "notarization/enable"), false));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Apple ID email"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_id_password", PROPERTY_HINT_PLACEHOLDER_TEXT, "Enable two-factor authentication and provide app-specific password"), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "notarization/apple_team_id", PROPERTY_HINT_PLACEHOLDER_TEXT, "Provide team ID if your Apple ID belongs to multiple teams"), ""));
#endif
r_options->push_back(ExportOption(PropertyInfo(Variant::BOOL, "texture_format/s3tc"), true));
@@ -148,7 +174,6 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
}
void _rgba8_to_packbits_encode(int p_ch, int p_size, Vector<uint8_t> &p_source, Vector<uint8_t> &p_dest) {
-
int src_len = p_size * p_size;
Vector<uint8_t> result;
@@ -163,7 +188,6 @@ void _rgba8_to_packbits_encode(int p_ch, int p_size, Vector<uint8_t> &p_source,
uint8_t cur = p_source.ptr()[i * 4 + p_ch];
if (i < src_len - 2) {
-
if ((p_source.ptr()[(i + 1) * 4 + p_ch] == cur) && (p_source.ptr()[(i + 2) * 4 + p_ch] == cur)) {
if (buf_size > 0) {
result.write[res_size++] = (uint8_t)(buf_size - 1);
@@ -215,7 +239,6 @@ void _rgba8_to_packbits_encode(int p_ch, int p_size, Vector<uint8_t> &p_source,
}
void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_t> &p_data) {
-
Ref<ImageTexture> it = memnew(ImageTexture);
Vector<uint8_t> data;
@@ -320,7 +343,6 @@ void EditorExportPlatformOSX::_make_icon(const Ref<Image> &p_icon, Vector<uint8_
}
void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset, Vector<uint8_t> &plist, const String &p_binary) {
-
String str;
String strnew;
str.parse_utf8((const char *)plist.ptr(), plist.size());
@@ -332,8 +354,8 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
strnew += lines[i].replace("$name", p_binary) + "\n";
} else if (lines[i].find("$info") != -1) {
strnew += lines[i].replace("$info", p_preset->get("application/info")) + "\n";
- } else if (lines[i].find("$identifier") != -1) {
- strnew += lines[i].replace("$identifier", p_preset->get("application/identifier")) + "\n";
+ } else if (lines[i].find("$bundle_identifier") != -1) {
+ strnew += lines[i].replace("$bundle_identifier", p_preset->get("application/bundle_identifier")) + "\n";
} else if (lines[i].find("$short_version") != -1) {
strnew += lines[i].replace("$short_version", p_preset->get("application/short_version")) + "\n";
} else if (lines[i].find("$version") != -1) {
@@ -369,7 +391,54 @@ void EditorExportPlatformOSX::_fix_plist(const Ref<EditorExportPreset> &p_preset
- and then wrap it up in a DMG
**/
+Error EditorExportPlatformOSX::_notarize(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+#ifdef OSX_ENABLED
+ List<String> args;
+
+ args.push_back("altool");
+ args.push_back("--notarize-app");
+
+ args.push_back("--primary-bundle-id");
+ args.push_back(p_preset->get("application/bundle_identifier"));
+
+ args.push_back("--username");
+ args.push_back(p_preset->get("notarization/apple_id_name"));
+
+ args.push_back("--password");
+ args.push_back(p_preset->get("notarization/apple_id_password"));
+
+ args.push_back("--type");
+ args.push_back("osx");
+
+ if (p_preset->get("notarization/apple_team_id")) {
+ args.push_back("--asc-provider");
+ args.push_back(p_preset->get("notarization/apple_team_id"));
+ }
+
+ args.push_back("--file");
+ args.push_back(p_path);
+
+ String str;
+ Error err = OS::get_singleton()->execute("xcrun", args, true, nullptr, &str, nullptr, true);
+ ERR_FAIL_COND_V(err != OK, err);
+
+ print_line("altool (" + p_path + "):\n" + str);
+ if (str.find("RequestUUID") == -1) {
+ EditorNode::add_io_error("altool: " + str);
+ return FAILED;
+ } else {
+ print_line("Note: The notarization process generally takes less than an hour. When the process is completed, you'll receive an email.");
+ print_line(" You can check progress manually by opening a Terminal and running the following command:");
+ print_line(" \"xcrun altool --notarization-history 0 -u <your email> -p <app-specific pwd>\"");
+ }
+
+#endif
+
+ return OK;
+}
+
Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path) {
+#ifdef OSX_ENABLED
List<String> args;
if (p_preset->get("codesign/timestamp")) {
@@ -380,8 +449,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
args.push_back("runtime");
}
- if (p_preset->get("codesign/entitlements") != "") {
- /* this should point to our entitlements.plist file that sandboxes our application, I don't know if this should also be placed in our app bundle */
+ if ((p_preset->get("codesign/entitlements") != "") && (p_path.get_extension() != "dmg")) {
args.push_back("--entitlements");
args.push_back(p_preset->get("codesign/entitlements"));
}
@@ -405,7 +473,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
Error err = OS::get_singleton()->execute("codesign", args, true, nullptr, &str, nullptr, true);
ERR_FAIL_COND_V(err != OK, err);
- print_line("codesign (" + p_path + "): " + str);
+ print_line("codesign (" + p_path + "):\n" + str);
if (str.find("no identity found") != -1) {
EditorNode::add_io_error("codesign: no identity found");
return FAILED;
@@ -414,6 +482,7 @@ Error EditorExportPlatformOSX::_code_sign(const Ref<EditorExportPreset> &p_prese
EditorNode::add_io_error("codesign: invalid entitlements file");
return FAILED;
}
+#endif
return OK;
}
@@ -458,10 +527,11 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
EditorProgress ep("export", "Exporting for OSX", 3, true);
- if (p_debug)
+ if (p_debug) {
src_pkg_name = p_preset->get("custom_template/debug");
- else
+ } else {
src_pkg_name = p_preset->get("custom_template/release");
+ }
if (src_pkg_name == "") {
String err;
@@ -485,7 +555,6 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
unzFile src_pkg_zip = unzOpen2(src_pkg_name.utf8().get_data(), &io);
if (!src_pkg_zip) {
-
EditorNode::add_io_error("Could not find template app to export:\n" + src_pkg_name);
return ERR_FILE_NOT_FOUND;
}
@@ -495,64 +564,54 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
String binary_to_use = "godot_osx_" + String(p_debug ? "debug" : "release") + ".64";
String pkg_name;
- if (p_preset->get("application/name") != "")
+ if (p_preset->get("application/name") != "") {
pkg_name = p_preset->get("application/name"); // app_name
- else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "")
+ } else if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") {
pkg_name = String(ProjectSettings::get_singleton()->get("application/config/name"));
- else
+ } else {
pkg_name = "Unnamed";
+ }
String pkg_name_safe = OS::get_singleton()->get_safe_dir_name(pkg_name);
Error err = OK;
String tmp_app_path_name = "";
- zlib_filefunc_def io2 = io;
- FileAccess *dst_f = nullptr;
- io2.opaque = &dst_f;
- zipFile dst_pkg_zip = nullptr;
DirAccess *tmp_app_path = nullptr;
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);
- tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);
- if (!tmp_app_path) {
- err = ERR_CANT_CREATE;
- }
- // Create our folder structure or rely on unzip?
- if (err == OK) {
- print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
- err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/MacOS");
- }
+ // 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);
+ tmp_app_path = DirAccess::create_for_path(tmp_app_path_name);
+ if (!tmp_app_path) {
+ err = ERR_CANT_CREATE;
+ }
- if (err == OK) {
- print_line("Creating " + tmp_app_path_name + "/Contents/Frameworks");
- err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks");
- }
+ // Create our folder structure.
+ if (err == OK) {
+ print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
+ err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/MacOS");
+ }
- if (err == OK) {
- print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
- err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
- }
- } else {
- // Open our destination zip file
- dst_pkg_zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io2);
- if (!dst_pkg_zip) {
- err = ERR_CANT_CREATE;
- }
+ if (err == OK) {
+ print_line("Creating " + tmp_app_path_name + "/Contents/Frameworks");
+ err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks");
}
- // Now process our template
+ if (err == OK) {
+ print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
+ err = tmp_app_path->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
+ }
+
+ // Now process our template.
bool found_binary = false;
int total_size = 0;
while (ret == UNZ_OK && err == OK) {
bool is_execute = false;
- //get filename
+ // Get filename.
unz_file_info info;
char fname[16384];
ret = unzGetCurrentFileInfo(src_pkg_zip, &info, fname, 16384, nullptr, 0, nullptr, 0);
@@ -562,13 +621,12 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
Vector<uint8_t> data;
data.resize(info.uncompressed_size);
- //read
+ // Read.
unzOpenCurrentFile(src_pkg_zip);
unzReadCurrentFile(src_pkg_zip, data.ptrw(), data.size());
unzCloseCurrentFile(src_pkg_zip);
- //write
-
+ // Write.
file = file.replace_first("osx_template.app/", "");
if (file == "Contents/Info.plist") {
@@ -578,7 +636,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
if (file.begins_with("Contents/MacOS/godot_")) {
if (file != "Contents/MacOS/" + binary_to_use) {
ret = unzGoToNextFile(src_pkg_zip);
- continue; //ignore!
+ continue; // skip
}
found_binary = true;
is_execute = true;
@@ -586,12 +644,13 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
if (file == "Contents/Resources/icon.icns") {
- //see if there is an icon
+ // See if there is an icon.
String iconpath;
- if (p_preset->get("application/icon") != "")
+ if (p_preset->get("application/icon") != "") {
iconpath = p_preset->get("application/icon");
- else
+ } else {
iconpath = ProjectSettings::get_singleton()->get("application/config/icon");
+ }
if (iconpath != "") {
if (iconpath.get_extension() == "icns") {
@@ -614,18 +673,17 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
}
if (data.size() > 0) {
-
if (file.find("/data.mono.osx.64.release_debug/") != -1) {
if (!p_debug) {
ret = unzGoToNextFile(src_pkg_zip);
- continue; //skip
+ continue; // skip
}
file = file.replace("/data.mono.osx.64.release_debug/", "/data_" + pkg_name_safe + "/");
}
if (file.find("/data.mono.osx.64.release/") != -1) {
if (p_debug) {
ret = unzGoToNextFile(src_pkg_zip);
- continue; //skip
+ continue; // skip
}
file = file.replace("/data.mono.osx.64.release/", "/data_" + pkg_name_safe + "/");
}
@@ -633,62 +691,31 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
print_line("ADDING: " + file + " size: " + itos(data.size()));
total_size += data.size();
- if (export_format == "dmg") {
- // write it into our application bundle
- file = tmp_app_path_name.plus_file(file);
- if (err == OK) {
- err = tmp_app_path->make_dir_recursive(file.get_base_dir());
- }
- if (err == OK) {
- // write the file, need to add chmod
- FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
- if (f) {
- f->store_buffer(data.ptr(), data.size());
- f->close();
- if (is_execute) {
- // Chmod with 0755 if the file is executable
- FileAccess::set_unix_permissions(file, 0755);
- }
- memdelete(f);
- } else {
- err = ERR_CANT_CREATE;
+ // Write it into our application bundle.
+ file = tmp_app_path_name.plus_file(file);
+ if (err == OK) {
+ err = tmp_app_path->make_dir_recursive(file.get_base_dir());
+ }
+ if (err == OK) {
+ FileAccess *f = FileAccess::open(file, FileAccess::WRITE);
+ if (f) {
+ f->store_buffer(data.ptr(), data.size());
+ f->close();
+ if (is_execute) {
+ // chmod with 0755 if the file is executable.
+ FileAccess::set_unix_permissions(file, 0755);
}
+ memdelete(f);
+ } else {
+ err = ERR_CANT_CREATE;
}
- } else {
- // add it to our zip file
- file = pkg_name + ".app/" + file;
-
- zip_fileinfo fi;
- fi.tmz_date.tm_hour = info.tmu_date.tm_hour;
- fi.tmz_date.tm_min = info.tmu_date.tm_min;
- fi.tmz_date.tm_sec = info.tmu_date.tm_sec;
- fi.tmz_date.tm_mon = info.tmu_date.tm_mon;
- fi.tmz_date.tm_mday = info.tmu_date.tm_mday;
- fi.tmz_date.tm_year = info.tmu_date.tm_year;
- fi.dosDate = info.dosDate;
- fi.internal_fa = info.internal_fa;
- fi.external_fa = info.external_fa;
-
- zipOpenNewFileInZip(dst_pkg_zip,
- file.utf8().get_data(),
- &fi,
- nullptr,
- 0,
- nullptr,
- 0,
- nullptr,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
- zipWriteInFileInZip(dst_pkg_zip, data.ptr(), data.size());
- zipCloseFileInZip(dst_pkg_zip);
}
}
ret = unzGoToNextFile(src_pkg_zip);
}
- // we're done with our source zip
+ // We're done with our source zip.
unzClose(src_pkg_zip);
if (!found_binary) {
@@ -701,124 +728,143 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
return ERR_SKIP;
}
- 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);
+ 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);
- // see if we can code sign our new package
- bool sign_enabled = p_preset->get("codesign/enable");
+ // See if we can code sign our new package.
+ bool sign_enabled = p_preset->get("codesign/enable");
- if (err == OK) {
- DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
- for (int i = 0; i < shared_objects.size(); i++) {
- err = da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
- if (err == OK && sign_enabled) {
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
- }
+ if (err == OK) {
+ DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+ for (int i = 0; i < shared_objects.size(); i++) {
+ err = da->copy(shared_objects[i].path, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
+ if (err == OK && sign_enabled) {
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + shared_objects[i].path.get_file());
}
- memdelete(da);
}
+ memdelete(da);
+ }
- if (err == OK && sign_enabled) {
- if (ep.step("Code signing bundle", 2)) {
- return ERR_SKIP;
- }
-
- // the order in which we code sign is important, this is a bit of a shame or we could do this in our loop that extracts the files from our ZIP
-
- // start with our application
- err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name);
-
- ///@TODO we should check the contents of /Contents/Frameworks for frameworks to sign
+ if (err == OK && sign_enabled) {
+ if (ep.step("Code signing bundle", 2)) {
+ return ERR_SKIP;
}
+ err = _code_sign(p_preset, tmp_app_path_name + "/Contents/MacOS/" + pkg_name);
+ }
- // and finally create a DMG
+ if (export_format == "dmg") {
+ // Create a DMG.
if (err == OK) {
if (ep.step("Making DMG", 3)) {
return ERR_SKIP;
}
err = _create_dmg(p_path, pkg_name, tmp_app_path_name);
}
-
- // Clean up temporary .app dir
- OS::get_singleton()->move_to_trash(tmp_app_path_name);
-
- } else { // pck
-
- String pack_path = EditorSettings::get_singleton()->get_cache_dir().plus_file(pkg_name + ".pck");
-
- Vector<SharedObject> shared_objects;
- err = save_pack(p_preset, pack_path, &shared_objects);
-
- if (err == OK) {
- zipOpenNewFileInZip(dst_pkg_zip,
- (pkg_name + ".app/Contents/Resources/" + pkg_name + ".pck").utf8().get_data(),
- nullptr,
- nullptr,
- 0,
- nullptr,
- 0,
- nullptr,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
- FileAccess *pf = FileAccess::open(pack_path, FileAccess::READ);
- if (pf) {
- const int BSIZE = 16384;
- uint8_t buf[BSIZE];
-
- while (true) {
-
- int r = pf->get_buffer(buf, BSIZE);
- if (r <= 0)
- break;
- zipWriteInFileInZip(dst_pkg_zip, buf, r);
- }
-
- zipCloseFileInZip(dst_pkg_zip);
- memdelete(pf);
- } else {
- err = ERR_CANT_OPEN;
+ // Sign DMG.
+ if (err == OK && sign_enabled) {
+ if (ep.step("Code signing DMG", 3)) {
+ return ERR_SKIP;
}
+ err = _code_sign(p_preset, p_path);
}
-
+ } else {
+ // Create ZIP.
if (err == OK) {
- //add shared objects
- for (int i = 0; i < shared_objects.size(); i++) {
- Vector<uint8_t> file = FileAccess::get_file_as_array(shared_objects[i].path);
- ERR_CONTINUE(file.empty());
-
- zipOpenNewFileInZip(dst_pkg_zip,
- (pkg_name + ".app/Contents/Frameworks/").plus_file(shared_objects[i].path.get_file()).utf8().get_data(),
- nullptr,
- nullptr,
- 0,
- nullptr,
- 0,
- nullptr,
- Z_DEFLATED,
- Z_DEFAULT_COMPRESSION);
-
- zipWriteInFileInZip(dst_pkg_zip, file.ptr(), file.size());
- zipCloseFileInZip(dst_pkg_zip);
+ if (ep.step("Making ZIP", 3)) {
+ return ERR_SKIP;
+ }
+ if (FileAccess::exists(p_path)) {
+ OS::get_singleton()->move_to_trash(p_path);
}
+
+ FileAccess *dst_f = nullptr;
+ zlib_filefunc_def io_dst = zipio_create_io_from_file(&dst_f);
+ zipFile zip = zipOpen2(p_path.utf8().get_data(), APPEND_STATUS_CREATE, nullptr, &io_dst);
+
+ _zip_folder_recursive(zip, EditorSettings::get_singleton()->get_cache_dir(), pkg_name + ".app", pkg_name);
+
+ zipClose(zip, nullptr);
}
+ }
- // Clean up generated file.
- DirAccess::remove_file_or_error(pack_path);
+ bool noto_enabled = p_preset->get("notarization/enable");
+ if (err == OK && noto_enabled) {
+ if (ep.step("Sending archive for notarization", 4)) {
+ return ERR_SKIP;
+ }
+ err = _notarize(p_preset, p_path);
}
- }
- if (dst_pkg_zip) {
- zipClose(dst_pkg_zip, nullptr);
+ // Clean up temporary .app dir.
+ OS::get_singleton()->move_to_trash(tmp_app_path_name);
}
return err;
}
-bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
+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);
+ da->list_dir_begin();
+ String f;
+ while ((f = da->get_next()) != "") {
+ if (f == "." || f == "..") {
+ continue;
+ }
+ 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));
+
+ OS::Time time = OS::get_singleton()->get_time();
+ OS::Date date = OS::get_singleton()->get_date();
+
+ zip_fileinfo zipfi;
+ zipfi.tmz_date.tm_hour = time.hour;
+ zipfi.tmz_date.tm_mday = date.day;
+ zipfi.tmz_date.tm_min = time.min;
+ zipfi.tmz_date.tm_mon = date.month - 1; // Note: "tm" month range - 0..11, Godot month range - 1..12, http://www.cplusplus.com/reference/ctime/tm/
+ zipfi.tmz_date.tm_sec = time.sec;
+ zipfi.tmz_date.tm_year = date.year;
+ zipfi.dosDate = 0;
+ // 0100000: regular file type
+ // 0000755: permissions rwxr-xr-x
+ // 0000644: permissions rw-r--r--
+ uint32_t _mode = (is_executable ? 0100755 : 0100644);
+ zipfi.external_fa = (_mode << 16L) | !(_mode & 0200);
+ zipfi.internal_fa = 0;
+
+ zipOpenNewFileInZip4(p_zip,
+ p_folder.plus_file(f).utf8().get_data(),
+ &zipfi,
+ nullptr,
+ 0,
+ nullptr,
+ 0,
+ nullptr,
+ Z_DEFLATED,
+ Z_DEFAULT_COMPRESSION,
+ 0,
+ -MAX_WBITS,
+ DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY,
+ nullptr,
+ 0,
+ 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());
+ zipCloseFileInZip(p_zip);
+ }
+ }
+ da->list_dir_end();
+ memdelete(da);
+}
+bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
String err;
bool valid = false;
@@ -843,13 +889,48 @@ bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset
valid = dvalid || rvalid;
r_missing_templates = !valid;
- if (!err.empty())
+ String identifier = p_preset->get("application/bundle_identifier");
+ String pn_err;
+ if (!is_package_name_valid(identifier, &pn_err)) {
+ err += TTR("Invalid bundle identifier:") + " " + pn_err + "\n";
+ valid = false;
+ }
+
+ bool sign_enabled = p_preset->get("codesign/enable");
+ if (sign_enabled) {
+ if (p_preset->get("codesign/identity") == "") {
+ err += TTR("Codesign: identity not specified.") + "\n";
+ valid = false;
+ }
+ }
+ bool noto_enabled = p_preset->get("notarization/enable");
+ if (noto_enabled) {
+ if (!sign_enabled) {
+ err += TTR("Notarization: code signing required.") + "\n";
+ valid = false;
+ }
+ bool hr_enabled = p_preset->get("codesign/hardened_runtime");
+ if (!hr_enabled) {
+ err += TTR("Notarization: hardened runtime required.") + "\n";
+ valid = false;
+ }
+ if (p_preset->get("notarization/apple_id_name") == "") {
+ err += TTR("Notarization: Apple ID name not specified.") + "\n";
+ valid = false;
+ }
+ if (p_preset->get("notarization/apple_id_password") == "") {
+ err += TTR("Notarization: Apple ID password not specified.") + "\n";
+ valid = false;
+ }
+ }
+
+ if (!err.empty()) {
r_error = err;
+ }
return valid;
}
EditorExportPlatformOSX::EditorExportPlatformOSX() {
-
Ref<Image> img = memnew(Image(_osx_logo));
logo.instance();
logo->create_from_image(img);
@@ -859,7 +940,6 @@ EditorExportPlatformOSX::~EditorExportPlatformOSX() {
}
void register_osx_exporter() {
-
Ref<EditorExportPlatformOSX> platform;
platform.instance();
diff --git a/platform/osx/godot_main_osx.mm b/platform/osx/godot_main_osx.mm
index eacd2b5cc6..4e73d5441c 100644
--- a/platform/osx/godot_main_osx.mm
+++ b/platform/osx/godot_main_osx.mm
@@ -36,9 +36,8 @@
#include <unistd.h>
int main(int argc, char **argv) {
-
#if defined(VULKAN_ENABLED)
- //MoltenVK - enable full component swizzling support
+ // MoltenVK - enable full component swizzling support
setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
#endif
@@ -61,6 +60,9 @@ int main(int argc, char **argv) {
OS_OSX os;
Error err;
+ // We must override main when testing is enabled
+ TEST_MAIN_OVERRIDE
+
if (os.open_with_filename != "") {
char *argv_c = (char *)malloc(os.open_with_filename.utf8().size());
memcpy(argv_c, os.open_with_filename.utf8().get_data(), os.open_with_filename.utf8().size());
diff --git a/platform/osx/joypad_osx.cpp b/platform/osx/joypad_osx.cpp
index 643acd8944..cfc371710b 100644
--- a/platform/osx/joypad_osx.cpp
+++ b/platform/osx/joypad_osx.cpp
@@ -98,6 +98,7 @@ int joypad::get_hid_element_state(rec_element *p_element) const {
}
return value;
}
+
void joypad::add_hid_element(IOHIDElementRef p_element) {
const CFTypeID elementTypeID = p_element ? CFGetTypeID(p_element) : 0;
@@ -240,7 +241,6 @@ static bool is_joypad(IOHIDDeviceRef p_device_ref) {
}
void JoypadOSX::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) {
-
if (p_res != kIOReturnSuccess || have_device(p_device)) {
return;
}
@@ -264,7 +264,6 @@ void JoypadOSX::_device_added(IOReturn p_res, IOHIDDeviceRef p_device) {
}
void JoypadOSX::_device_removed(IOReturn p_res, IOHIDDeviceRef p_device) {
-
int device = get_joy_ref(p_device);
ERR_FAIL_COND(device == -1);
@@ -274,7 +273,6 @@ void JoypadOSX::_device_removed(IOReturn p_res, IOHIDDeviceRef p_device) {
}
static String _hex_str(uint8_t p_byte) {
-
static const char *dict = "0123456789abcdef";
char ret[3];
ret[2] = 0;
@@ -286,7 +284,6 @@ static String _hex_str(uint8_t p_byte) {
}
bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) {
-
p_joy->device_ref = p_device_ref;
/* get device name */
String name;
@@ -314,9 +311,16 @@ bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) {
if (refCF) {
CFNumberGetValue((CFNumberRef)refCF, kCFNumberSInt32Type, &product_id);
}
+
+ int version = 0;
+ refCF = IOHIDDeviceGetProperty(p_device_ref, CFSTR(kIOHIDVersionNumberKey));
+ if (refCF) {
+ CFNumberGetValue((CFNumberRef)refCF, kCFNumberSInt32Type, &version);
+ }
+
if (vendor && product_id) {
char uid[128];
- sprintf(uid, "%04x%08x%04x%08x", OSSwapHostToBigInt32(vendor), 0, OSSwapHostToBigInt32(product_id), 0);
+ sprintf(uid, "%08x%08x%08x%08x", OSSwapHostToBigInt32(3), OSSwapHostToBigInt32(vendor), OSSwapHostToBigInt32(product_id), OSSwapHostToBigInt32(version));
input->joy_connection_changed(id, true, name, uid);
} else {
//bluetooth device
@@ -346,7 +350,6 @@ bool JoypadOSX::configure_joypad(IOHIDDeviceRef p_device_ref, joypad *p_joy) {
} \
}
bool joypad::config_force_feedback(io_service_t p_service) {
-
HRESULT ret = FFCreateDevice(p_service, &ff_device);
ERR_FAIL_COND_V(ret != FF_OK, false);
@@ -368,13 +371,13 @@ bool joypad::config_force_feedback(io_service_t p_service) {
#define TEST_FF(ff) (features.supportedEffects & (ff))
bool joypad::check_ff_features() {
-
FFCAPABILITIES features;
HRESULT ret = FFDeviceGetForceFeedbackCapabilities(ff_device, &features);
if (ret == FF_OK && (features.supportedEffects & FFCAP_ET_CONSTANTFORCE)) {
uint32_t val;
ret = FFDeviceGetForceFeedbackProperty(ff_device, FFPROP_FFGAIN, &val, sizeof(val));
- if (ret != FF_OK) return false;
+ if (ret != FF_OK)
+ return false;
int num_axes = features.numFfAxes;
ff_axes = (DWORD *)memalloc(sizeof(DWORD) * num_axes);
ff_directions = (LONG *)memalloc(sizeof(LONG) * num_axes);
@@ -395,38 +398,38 @@ bool joypad::check_ff_features() {
static int process_hat_value(int p_min, int p_max, int p_value) {
int range = (p_max - p_min + 1);
int value = p_value - p_min;
- int hat_value = InputFilter::HAT_MASK_CENTER;
+ int hat_value = Input::HAT_MASK_CENTER;
if (range == 4) {
value *= 2;
}
switch (value) {
case 0:
- hat_value = InputFilter::HAT_MASK_UP;
+ hat_value = Input::HAT_MASK_UP;
break;
case 1:
- hat_value = InputFilter::HAT_MASK_UP | InputFilter::HAT_MASK_RIGHT;
+ hat_value = Input::HAT_MASK_UP | Input::HAT_MASK_RIGHT;
break;
case 2:
- hat_value = InputFilter::HAT_MASK_RIGHT;
+ hat_value = Input::HAT_MASK_RIGHT;
break;
case 3:
- hat_value = InputFilter::HAT_MASK_DOWN | InputFilter::HAT_MASK_RIGHT;
+ hat_value = Input::HAT_MASK_DOWN | Input::HAT_MASK_RIGHT;
break;
case 4:
- hat_value = InputFilter::HAT_MASK_DOWN;
+ hat_value = Input::HAT_MASK_DOWN;
break;
case 5:
- hat_value = InputFilter::HAT_MASK_DOWN | InputFilter::HAT_MASK_LEFT;
+ hat_value = Input::HAT_MASK_DOWN | Input::HAT_MASK_LEFT;
break;
case 6:
- hat_value = InputFilter::HAT_MASK_LEFT;
+ hat_value = Input::HAT_MASK_LEFT;
break;
case 7:
- hat_value = InputFilter::HAT_MASK_UP | InputFilter::HAT_MASK_LEFT;
+ hat_value = Input::HAT_MASK_UP | Input::HAT_MASK_LEFT;
break;
default:
- hat_value = InputFilter::HAT_MASK_CENTER;
+ hat_value = Input::HAT_MASK_CENTER;
break;
}
return hat_value;
@@ -438,8 +441,8 @@ void JoypadOSX::poll_joypads() const {
}
}
-static const InputFilter::JoyAxis axis_correct(int p_value, int p_min, int p_max) {
- InputFilter::JoyAxis jx;
+static const Input::JoyAxis axis_correct(int p_value, int p_min, int p_max) {
+ Input::JoyAxis jx;
if (p_min < 0) {
jx.min = -1;
if (p_value < 0) {
@@ -509,14 +512,16 @@ void JoypadOSX::joypad_vibration_stop(int p_id, uint64_t p_timestamp) {
int JoypadOSX::get_joy_index(int p_id) const {
for (int i = 0; i < device_list.size(); i++) {
- if (device_list[i].id == p_id) return i;
+ if (device_list[i].id == p_id)
+ return i;
}
return -1;
}
int JoypadOSX::get_joy_ref(IOHIDDeviceRef p_device) const {
for (int i = 0; i < device_list.size(); i++) {
- if (device_list[i].device_ref == p_device) return i;
+ if (device_list[i].device_ref == p_device)
+ return i;
}
return -1;
}
@@ -556,7 +561,6 @@ static CFDictionaryRef create_match_dictionary(const UInt32 page, const UInt32 u
}
void JoypadOSX::config_hid_manager(CFArrayRef p_matching_array) const {
-
CFRunLoopRef runloop = CFRunLoopGetCurrent();
IOReturn ret = IOHIDManagerOpen(hid_manager, kIOHIDOptionsTypeNone);
ERR_FAIL_COND(ret != kIOReturnSuccess);
@@ -571,7 +575,7 @@ void JoypadOSX::config_hid_manager(CFArrayRef p_matching_array) const {
}
}
-JoypadOSX::JoypadOSX(InputFilter *in) {
+JoypadOSX::JoypadOSX(Input *in) {
self = this;
input = in;
@@ -600,7 +604,6 @@ JoypadOSX::JoypadOSX(InputFilter *in) {
}
JoypadOSX::~JoypadOSX() {
-
for (int i = 0; i < device_list.size(); i++) {
device_list.write[i].free();
}
diff --git a/platform/osx/joypad_osx.h b/platform/osx/joypad_osx.h
index 62027c6a30..dc238e68e4 100644
--- a/platform/osx/joypad_osx.h
+++ b/platform/osx/joypad_osx.h
@@ -40,7 +40,7 @@
#include <ForceFeedback/ForceFeedbackConstants.h>
#include <IOKit/hid/IOHIDLib.h>
-#include "core/input/input_filter.h"
+#include "core/input/input.h"
struct rec_element {
IOHIDElementRef ref;
@@ -88,13 +88,12 @@ struct joypad {
};
class JoypadOSX {
-
enum {
JOYPADS_MAX = 16,
};
private:
- InputFilter *input;
+ Input *input;
IOHIDManagerRef hid_manager;
Vector<joypad> device_list;
@@ -118,7 +117,7 @@ public:
void _device_added(IOReturn p_res, IOHIDDeviceRef p_device);
void _device_removed(IOReturn p_res, IOHIDDeviceRef p_device);
- JoypadOSX(InputFilter *in);
+ JoypadOSX(Input *in);
~JoypadOSX();
};
diff --git a/platform/osx/logo.png b/platform/osx/logo.png
index 834bbf3ba6..b5a660b165 100644
--- a/platform/osx/logo.png
+++ b/platform/osx/logo.png
Binary files differ
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index d2c67cff9f..9204a145bf 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -31,7 +31,7 @@
#ifndef OS_OSX_H
#define OS_OSX_H
-#include "core/input/input_filter.h"
+#include "core/input/input.h"
#include "crash_handler_osx.h"
#include "drivers/coreaudio/audio_driver_coreaudio.h"
#include "drivers/coremidi/midi_driver_coremidi.h"
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index 49cb056c9f..c4eb5407af 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -60,39 +60,31 @@ public:
switch (p_type) {
case ERR_WARNING:
- if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
- os_log_info(OS_LOG_DEFAULT,
- "WARNING: %{public}s\nat: %{public}s (%{public}s:%i)",
- err_details, p_function, p_file, p_line);
- }
+ os_log_info(OS_LOG_DEFAULT,
+ "WARNING: %{public}s\nat: %{public}s (%{public}s:%i)",
+ err_details, p_function, p_file, p_line);
logf_error("\E[1;33mWARNING:\E[0;93m %s\n", err_details);
logf_error("\E[0;90m at: %s (%s:%i)\E[0m\n", p_function, p_file, p_line);
break;
case ERR_SCRIPT:
- if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
- os_log_error(OS_LOG_DEFAULT,
- "SCRIPT ERROR: %{public}s\nat: %{public}s (%{public}s:%i)",
- err_details, p_function, p_file, p_line);
- }
+ os_log_error(OS_LOG_DEFAULT,
+ "SCRIPT ERROR: %{public}s\nat: %{public}s (%{public}s:%i)",
+ err_details, p_function, p_file, p_line);
logf_error("\E[1;35mSCRIPT ERROR:\E[0;95m %s\n", err_details);
logf_error("\E[0;90m at: %s (%s:%i)\E[0m\n", p_function, p_file, p_line);
break;
case ERR_SHADER:
- if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
- os_log_error(OS_LOG_DEFAULT,
- "SHADER ERROR: %{public}s\nat: %{public}s (%{public}s:%i)",
- err_details, p_function, p_file, p_line);
- }
+ os_log_error(OS_LOG_DEFAULT,
+ "SHADER ERROR: %{public}s\nat: %{public}s (%{public}s:%i)",
+ err_details, p_function, p_file, p_line);
logf_error("\E[1;36mSHADER ERROR:\E[0;96m %s\n", err_details);
logf_error("\E[0;90m at: %s (%s:%i)\E[0m\n", p_function, p_file, p_line);
break;
case ERR_ERROR:
default:
- if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_12) {
- os_log_error(OS_LOG_DEFAULT,
- "ERROR: %{public}s\nat: %{public}s (%{public}s:%i)",
- err_details, p_function, p_file, p_line);
- }
+ os_log_error(OS_LOG_DEFAULT,
+ "ERROR: %{public}s\nat: %{public}s (%{public}s:%i)",
+ err_details, p_function, p_file, p_line);
logf_error("\E[1;31mERROR:\E[0;91m %s\n", err_details);
logf_error("\E[0;90m at: %s (%s:%i)\E[0m\n", p_function, p_file, p_line);
break;
@@ -136,7 +128,7 @@ void OS_OSX::initialize_core() {
}
void OS_OSX::initialize_joypads() {
- joypad_osx = memnew(JoypadOSX(InputFilter::get_singleton()));
+ joypad_osx = memnew(JoypadOSX(Input::get_singleton()));
}
void OS_OSX::initialize() {
@@ -147,7 +139,6 @@ void OS_OSX::initialize() {
}
void OS_OSX::finalize() {
-
#ifdef COREMIDI_ENABLED
midi_driver.close();
#endif
@@ -269,10 +260,8 @@ String OS_OSX::get_system_dir(SystemDir p_dir) const {
String ret;
if (found) {
-
NSArray *paths = NSSearchPathForDirectoriesInDomains(id, NSUserDomainMask, YES);
if (paths && [paths count] >= 1) {
-
char *utfs = strdup([[paths firstObject] UTF8String]);
ret.parse_utf8(utfs);
free(utfs);
@@ -283,7 +272,13 @@ String OS_OSX::get_system_dir(SystemDir p_dir) const {
}
Error OS_OSX::shell_open(String p_uri) {
- [[NSWorkspace sharedWorkspace] openURL:[[NSURL alloc] initWithString:[[NSString stringWithUTF8String:p_uri.utf8().get_data()] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]]];
+ NSString *string = [NSString stringWithUTF8String:p_uri.utf8().get_data()];
+ NSURL *uri = [[NSURL alloc] initWithString:string];
+ // Escape special characters in filenames
+ if (!uri || !uri.scheme || [uri.scheme isEqual:@"file"]) {
+ uri = [[NSURL alloc] initWithString:[string stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLFragmentAllowedCharacterSet]]];
+ }
+ [[NSWorkspace sharedWorkspace] openURL:uri];
return OK;
}
@@ -325,7 +320,7 @@ void OS_OSX::run() {
}
joypad_osx->process_joypads();
- if (Main::iteration() == true) {
+ if (Main::iteration()) {
quit = true;
}
} @catch (NSException *exception) {
diff --git a/platform/osx/platform_config.h b/platform/osx/platform_config.h
index 155f37ed55..e657aca955 100644
--- a/platform/osx/platform_config.h
+++ b/platform/osx/platform_config.h
@@ -30,5 +30,4 @@
#include <alloca.h>
-#define GLES2_INCLUDE_H "thirdparty/glad/glad/glad.h"
#define PTHREAD_RENAME_SELF
diff --git a/platform/osx/vulkan_context_osx.h b/platform/osx/vulkan_context_osx.h
index 09a5494ae8..e996f176a9 100644
--- a/platform/osx/vulkan_context_osx.h
+++ b/platform/osx/vulkan_context_osx.h
@@ -35,7 +35,6 @@
#include <AppKit/AppKit.h>
class VulkanContextOSX : public VulkanContext {
-
virtual const char *_get_platform_surface_extension() const;
public:
diff --git a/platform/osx/vulkan_context_osx.mm b/platform/osx/vulkan_context_osx.mm
index 320401cdcb..ec8745ff01 100644
--- a/platform/osx/vulkan_context_osx.mm
+++ b/platform/osx/vulkan_context_osx.mm
@@ -36,7 +36,6 @@ const char *VulkanContextOSX::_get_platform_surface_extension() const {
}
Error VulkanContextOSX::window_create(DisplayServer::WindowID p_window_id, id p_window, int p_width, int p_height) {
-
VkMacOSSurfaceCreateInfoMVK createInfo;
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = NULL;