diff options
Diffstat (limited to 'platform')
20 files changed, 357 insertions, 129 deletions
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp index d5de595d87..b0f16337ed 100644 --- a/platform/android/display_server_android.cpp +++ b/platform/android/display_server_android.cpp @@ -263,6 +263,24 @@ DisplayServer::WindowID DisplayServerAndroid::get_window_at_screen_position(cons return MAIN_WINDOW_ID; } +int64_t DisplayServerAndroid::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return 0; // Not supported. + } + case WINDOW_HANDLE: { + return (int64_t)((OS_Android *)OS::get_singleton())->get_godot_java()->get_activity(); + } + case WINDOW_VIEW: { + return 0; // Not supported. + } + default: { + return 0; + } + } +} + void DisplayServerAndroid::window_attach_instance_id(ObjectID p_instance, DisplayServer::WindowID p_window) { window_attached_instance_id = p_instance; } diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h index 3ef7ddaffc..23077a6529 100644 --- a/platform/android/display_server_android.h +++ b/platform/android/display_server_android.h @@ -125,6 +125,9 @@ public: virtual Vector<WindowID> get_window_list() const override; virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; + + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID) override; diff --git a/platform/iphone/display_server_iphone.h b/platform/iphone/display_server_iphone.h index 1bd5f8737b..7441550f67 100644 --- a/platform/iphone/display_server_iphone.h +++ b/platform/iphone/display_server_iphone.h @@ -136,6 +136,8 @@ public: virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + 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; diff --git a/platform/iphone/display_server_iphone.mm b/platform/iphone/display_server_iphone.mm index 2b4098988c..9491c9cf90 100644 --- a/platform/iphone/display_server_iphone.mm +++ b/platform/iphone/display_server_iphone.mm @@ -411,6 +411,24 @@ DisplayServer::WindowID DisplayServerIPhone::get_window_at_screen_position(const return MAIN_WINDOW_ID; } +int64_t DisplayServerIPhone::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(p_window != MAIN_WINDOW_ID, 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return 0; // Not supported. + } + case WINDOW_HANDLE: { + return (int64_t)AppDelegate.viewController; + } + case WINDOW_VIEW: { + return (int64_t)AppDelegate.viewController.godotView; + } + default: { + return 0; + } + } +} + void DisplayServerIPhone::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { window_attached_instance_id = p_instance; } diff --git a/platform/iphone/export/export_plugin.cpp b/platform/iphone/export/export_plugin.cpp index ea17f1ac61..fe00b1a3cd 100644 --- a/platform/iphone/export/export_plugin.cpp +++ b/platform/iphone/export/export_plugin.cpp @@ -83,7 +83,7 @@ void EditorExportPlatformIOS::get_export_options(List<ExportOption> *r_options) r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/app_store_team_id"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_debug"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "iPhone Developer")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_debug", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Developer"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "application/export_method_debug", PROPERTY_HINT_ENUM, "App Store,Development,Ad-Hoc,Enterprise"), 1)); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/provisioning_profile_uuid_release"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/code_sign_identity_release", PROPERTY_HINT_PLACEHOLDER_TEXT, "iPhone Distribution"), "")); @@ -178,6 +178,10 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ "scaleAspectFill", "scaleToFill" }; + String dbg_sign_id = p_preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : p_preset->get("application/code_sign_identity_debug"); + String rel_sign_id = p_preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : p_preset->get("application/code_sign_identity_release"); + bool dbg_manual = !p_preset->get("application/provisioning_profile_uuid_debug").operator String().is_empty() || (dbg_sign_id != "iPhone Developer"); + bool rel_manual = !p_preset->get("application/provisioning_profile_uuid_release").operator String().is_empty() || (rel_sign_id != "iPhone Distribution"); String str; String strnew; str.parse_utf8((const char *)pfile.ptr(), pfile.size()); @@ -218,13 +222,25 @@ void EditorExportPlatformIOS::_fix_config_file(const Ref<EditorExportPreset> &p_ strnew += lines[i].replace("$provisioning_profile_uuid_release", p_preset->get("application/provisioning_profile_uuid_release")) + "\n"; } else if (lines[i].find("$provisioning_profile_uuid_debug") != -1) { strnew += lines[i].replace("$provisioning_profile_uuid_debug", p_preset->get("application/provisioning_profile_uuid_debug")) + "\n"; + } else if (lines[i].find("$code_sign_style_debug") != -1) { + if (dbg_manual) { + strnew += lines[i].replace("$code_sign_style_debug", "Manual") + "\n"; + } else { + strnew += lines[i].replace("$code_sign_style_debug", "Automatic") + "\n"; + } + } else if (lines[i].find("$code_sign_style_release") != -1) { + if (rel_manual) { + strnew += lines[i].replace("$code_sign_style_release", "Manual") + "\n"; + } else { + strnew += lines[i].replace("$code_sign_style_release", "Automatic") + "\n"; + } } else if (lines[i].find("$provisioning_profile_uuid") != -1) { String uuid = p_debug ? p_preset->get("application/provisioning_profile_uuid_debug") : p_preset->get("application/provisioning_profile_uuid_release"); strnew += lines[i].replace("$provisioning_profile_uuid", uuid) + "\n"; } else if (lines[i].find("$code_sign_identity_debug") != -1) { - strnew += lines[i].replace("$code_sign_identity_debug", p_preset->get("application/code_sign_identity_debug")) + "\n"; + strnew += lines[i].replace("$code_sign_identity_debug", dbg_sign_id) + "\n"; } else if (lines[i].find("$code_sign_identity_release") != -1) { - strnew += lines[i].replace("$code_sign_identity_release", p_preset->get("application/code_sign_identity_release")) + "\n"; + strnew += lines[i].replace("$code_sign_identity_release", rel_sign_id) + "\n"; } else if (lines[i].find("$additional_plist_content") != -1) { strnew += lines[i].replace("$additional_plist_content", p_config.plist_content) + "\n"; } else if (lines[i].find("$godot_archs") != -1) { @@ -770,10 +786,18 @@ Error EditorExportPlatformIOS::_codesign(String p_file, void *p_userdata) { if (p_file.ends_with(".dylib")) { CodesignData *data = (CodesignData *)p_userdata; print_line(String("Signing ") + p_file); + + String sign_id; + if (data->debug) { + sign_id = data->preset->get("application/code_sign_identity_debug").operator String().is_empty() ? "iPhone Developer" : data->preset->get("application/code_sign_identity_debug"); + } else { + sign_id = data->preset->get("application/code_sign_identity_release").operator String().is_empty() ? "iPhone Distribution" : data->preset->get("application/code_sign_identity_release"); + } + List<String> codesign_args; codesign_args.push_back("-f"); codesign_args.push_back("-s"); - codesign_args.push_back(data->preset->get(data->debug ? "application/code_sign_identity_debug" : "application/code_sign_identity_release")); + codesign_args.push_back(sign_id); codesign_args.push_back(p_file); return OS::get_singleton()->execute("codesign", codesign_args); } @@ -1680,6 +1704,7 @@ Error EditorExportPlatformIOS::export_project(const Ref<EditorExportPreset> &p_p archive_args.push_back("-destination"); archive_args.push_back("generic/platform=iOS"); archive_args.push_back("archive"); + archive_args.push_back("-allowProvisioningUpdates"); archive_args.push_back("-archivePath"); archive_args.push_back(archive_path); String archive_str; diff --git a/platform/javascript/http_client_javascript.cpp b/platform/javascript/http_client_javascript.cpp index 45aa68ce7c..c946302862 100644 --- a/platform/javascript/http_client_javascript.cpp +++ b/platform/javascript/http_client_javascript.cpp @@ -87,6 +87,11 @@ Error HTTPClientJavaScript::request(Method p_method, const String &p_url, const ERR_FAIL_COND_V(port < 0, ERR_UNCONFIGURED); ERR_FAIL_COND_V(!p_url.begins_with("/"), ERR_INVALID_PARAMETER); + Error err = verify_headers(p_headers); + if (err) { + return err; + } + String url = (use_tls ? "https://" : "http://") + host + ":" + itos(port) + p_url; Vector<CharString> keeper; Vector<const char *> c_strings; diff --git a/platform/javascript/js/engine/config.js b/platform/javascript/js/engine/config.js index ba61b14eb7..a6f9c4614c 100644 --- a/platform/javascript/js/engine/config.js +++ b/platform/javascript/js/engine/config.js @@ -225,6 +225,8 @@ const InternalConfig = function (initConfig) { // eslint-disable-line no-unused- */ Config.prototype.update = function (opts) { const config = opts || {}; + // NOTE: We must explicitly pass the default, accessing it via + // the key will fail due to closure compiler renames. function parse(key, def) { if (typeof (config[key]) === 'undefined') { return def; diff --git a/platform/javascript/js/libs/library_godot_input.js b/platform/javascript/js/libs/library_godot_input.js index 7a4d0d8126..1e64c260f8 100644 --- a/platform/javascript/js/libs/library_godot_input.js +++ b/platform/javascript/js/libs/library_godot_input.js @@ -87,7 +87,7 @@ const GodotInputGamepads = { }, init: function (onchange) { - GodotEventListeners.samples = []; + GodotInputGamepads.samples = []; function add(pad) { const guid = GodotInputGamepads.get_guid(pad); const c_id = GodotRuntime.allocString(pad.id); diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index d4b4e26fba..6e2211c376 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -323,20 +323,21 @@ void DisplayServerX11::mouse_set_mode(MouseMode p_mode) { if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { //flush pending motion events _flush_mouse_motion(); - WindowData &main_window = windows[MAIN_WINDOW_ID]; + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + WindowData &window = windows[window_id]; if (XGrabPointer( - x11_display, main_window.x11_window, True, + x11_display, window.x11_window, True, ButtonPressMask | ButtonReleaseMask | PointerMotionMask, - GrabModeAsync, GrabModeAsync, windows[MAIN_WINDOW_ID].x11_window, None, CurrentTime) != GrabSuccess) { + GrabModeAsync, GrabModeAsync, window.x11_window, None, CurrentTime) != GrabSuccess) { ERR_PRINT("NO GRAB"); } if (mouse_mode == MOUSE_MODE_CAPTURED) { - center.x = main_window.size.width / 2; - center.y = main_window.size.height / 2; + center.x = window.size.width / 2; + center.y = window.size.height / 2; - XWarpPointer(x11_display, None, main_window.x11_window, + XWarpPointer(x11_display, None, window.x11_window, 0, 0, 0, 0, (int)center.x, (int)center.y); Input::get_singleton()->set_mouse_position(center); @@ -358,7 +359,8 @@ void DisplayServerX11::mouse_warp_to_position(const Point2i &p_to) { if (mouse_mode == MOUSE_MODE_CAPTURED) { last_mouse_pos = p_to; } else { - XWarpPointer(x11_display, None, windows[MAIN_WINDOW_ID].x11_window, + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + XWarpPointer(x11_display, None, windows[window_id].x11_window, 0, 0, 0, 0, (int)p_to.x, (int)p_to.y); } } @@ -1214,6 +1216,24 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) { windows.erase(p_id); } +int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(!windows.has(p_window), 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return (int64_t)x11_display; + } + case WINDOW_HANDLE: { + return (int64_t)windows[p_window].x11_window; + } + case WINDOW_VIEW: { + return 0; // Not supported. + } + default: { + return 0; + } + } +} + void DisplayServerX11::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd = windows[p_window]; @@ -1374,8 +1394,9 @@ int DisplayServerX11::window_get_current_screen(WindowID p_window) const { void DisplayServerX11::gl_window_make_current(DisplayServer::WindowID p_window_id) { #if defined(GLES3_ENABLED) - if (gl_manager) + if (gl_manager) { gl_manager->window_make_current(p_window_id); + } #endif } @@ -3394,7 +3415,7 @@ void DisplayServerX11::process_events() { DEBUG_LOG_X11("[%u] FocusIn window=%lu (%u), mode='%u' \n", frame, event.xfocus.window, window_id, event.xfocus.mode); WindowData &wd = windows[window_id]; - + last_focused_window = window_id; wd.focused = true; if (wd.xic) { @@ -3594,9 +3615,9 @@ void DisplayServerX11::process_events() { // The X11 API requires filtering one-by-one through the motion // notify events, in order to figure out which event is the one // generated by warping the mouse pointer. - + WindowID focused_window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; while (true) { - if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[MAIN_WINDOW_ID].size.width / 2 && event.xmotion.y == windows[MAIN_WINDOW_ID].size.height / 2) { + if (mouse_mode == MOUSE_MODE_CAPTURED && event.xmotion.x == windows[focused_window_id].size.width / 2 && event.xmotion.y == windows[focused_window_id].size.height / 2) { //this is likely the warp event since it was warped here center = Vector2(event.xmotion.x, event.xmotion.y); break; @@ -3671,9 +3692,8 @@ void DisplayServerX11::process_events() { // Reset to prevent lingering motion xi.relative_motion.x = 0; xi.relative_motion.y = 0; - if (mouse_mode == MOUSE_MODE_CAPTURED) { - pos = Point2i(windows[MAIN_WINDOW_ID].size.width / 2, windows[MAIN_WINDOW_ID].size.height / 2); + pos = Point2i(windows[focused_window_id].size.width / 2, windows[focused_window_id].size.height / 2); } Ref<InputEventMouseMotion> mm; diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index 508c3cab57..2d07361deb 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -143,7 +143,7 @@ class DisplayServerX11 : public DisplayServer { bool borderless = false; bool resize_disabled = false; Vector2i last_position_before_fs; - bool focused = false; + bool focused = true; bool minimized = false; unsigned int focus_order = 0; @@ -151,6 +151,8 @@ class DisplayServerX11 : public DisplayServer { Map<WindowID, WindowData> windows; + WindowID last_focused_window = INVALID_WINDOW_ID; + WindowID window_id_counter = MAIN_WINDOW_ID; WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect); @@ -317,6 +319,8 @@ public: virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + 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; diff --git a/platform/linuxbsd/gl_manager_x11.cpp b/platform/linuxbsd/gl_manager_x11.cpp index 1721d0e0b3..d3fb1d6705 100644 --- a/platform/linuxbsd/gl_manager_x11.cpp +++ b/platform/linuxbsd/gl_manager_x11.cpp @@ -68,8 +68,9 @@ static int ctxErrorHandler(Display *dpy, XErrorEvent *ev) { int GLManager_X11::_find_or_create_display(Display *p_x11_display) { for (unsigned int n = 0; n < _displays.size(); n++) { const GLDisplay &d = _displays[n]; - if (d.x11_display == p_x11_display) + if (d.x11_display == p_x11_display) { return n; + } } // create @@ -82,8 +83,7 @@ int GLManager_X11::_find_or_create_display(Display *p_x11_display) { GLDisplay &d = _displays[new_display_id]; d.context = memnew(GLManager_X11_Private); - ; - d.context->glx_context = 0; + d.context->glx_context = nullptr; //Error err = _create_context(d); _create_context(d); @@ -124,7 +124,7 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) { }; int fbcount; - GLXFBConfig fbconfig = 0; + GLXFBConfig fbconfig = nullptr; XVisualInfo *vi = nullptr; gl_display.x_swa.event_mask = StructureNotifyMask; @@ -137,8 +137,9 @@ Error GLManager_X11::_create_context(GLDisplay &gl_display) { for (int i = 0; i < fbcount; i++) { vi = (XVisualInfo *)glXGetVisualFromFBConfig(x11_display, fbc[i]); - if (!vi) + if (!vi) { continue; + } XRenderPictFormat *pict_format = XRenderFindVisualFormat(x11_display, vi->visual); if (!pict_format) { @@ -262,22 +263,26 @@ void GLManager_X11::window_destroy(DisplayServer::WindowID p_window_id) { } void GLManager_X11::release_current() { - if (!_current_window) + if (!_current_window) { return; + } glXMakeCurrent(_x_windisp.x11_display, None, nullptr); } void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) { - if (p_window_id == -1) + if (p_window_id == -1) { return; + } GLWindow &win = _windows[p_window_id]; - if (!win.in_use) + if (!win.in_use) { return; + } // noop - if (&win == _current_window) + if (&win == _current_window) { return; + } const GLDisplay &disp = get_display(win.gldisplay_id); @@ -287,8 +292,9 @@ void GLManager_X11::window_make_current(DisplayServer::WindowID p_window_id) { } void GLManager_X11::make_current() { - if (!_current_window) + if (!_current_window) { return; + } if (!_current_window->in_use) { WARN_PRINT("current window not in use!"); return; @@ -301,8 +307,9 @@ void GLManager_X11::swap_buffers() { // NO NEED TO CALL SWAP BUFFERS for each window... // see https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glXSwapBuffers.xml - if (!_current_window) + if (!_current_window) { return; + } if (!_current_window->in_use) { WARN_PRINT("current window not in use!"); return; @@ -335,19 +342,23 @@ void GLManager_X11::set_use_vsync(bool p_use) { } // we need an active window to get a display to set the vsync - if (!_current_window) + if (!_current_window) { return; + } const GLDisplay &disp = get_current_display(); if (!setup) { setup = true; String extensions = glXQueryExtensionsString(disp.x11_display, DefaultScreen(disp.x11_display)); - if (extensions.find("GLX_EXT_swap_control") != -1) + if (extensions.find("GLX_EXT_swap_control") != -1) { glXSwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalEXT"); - if (extensions.find("GLX_MESA_swap_control") != -1) + } + if (extensions.find("GLX_MESA_swap_control") != -1) { glXSwapIntervalMESA = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalMESA"); - if (extensions.find("GLX_SGI_swap_control") != -1) + } + if (extensions.find("GLX_SGI_swap_control") != -1) { glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddressARB((const GLubyte *)"glXSwapIntervalSGI"); + } } int val = p_use ? 1 : 0; if (glXSwapIntervalMESA) { @@ -357,8 +368,9 @@ void GLManager_X11::set_use_vsync(bool p_use) { } else if (glXSwapIntervalEXT) { GLXDrawable drawable = glXGetCurrentDrawable(); glXSwapIntervalEXT(disp.x11_display, drawable, val); - } else + } else { return; + } use_vsync = p_use; } diff --git a/platform/osx/display_server_osx.h b/platform/osx/display_server_osx.h index 4e2adc768f..4fc733fe2c 100644 --- a/platform/osx/display_server_osx.h +++ b/platform/osx/display_server_osx.h @@ -145,6 +145,8 @@ public: Map<WindowID, WindowData> windows; + WindowID last_focused_window = INVALID_WINDOW_ID; + WindowID window_id_counter = MAIN_WINDOW_ID; WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect); @@ -283,6 +285,8 @@ public: virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) override; virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const override; virtual void gl_window_make_current(DisplayServer::WindowID p_window_id) override; diff --git a/platform/osx/display_server_osx.mm b/platform/osx/display_server_osx.mm index 4e26044849..fec1fffe43 100644 --- a/platform/osx/display_server_osx.mm +++ b/platform/osx/display_server_osx.mm @@ -321,6 +321,7 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { } DS_OSX->window_focused = true; + DS_OSX->last_focused_window = window_id; DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN); } @@ -355,6 +356,7 @@ static NSCursor *_cursorFromSelector(SEL selector, SEL fallback = nil) { DisplayServerOSX::WindowData &wd = DS_OSX->windows[window_id]; DS_OSX->window_focused = true; + DS_OSX->last_focused_window = window_id; DS_OSX->_send_window_event(wd, DisplayServerOSX::WINDOW_EVENT_FOCUS_IN); } @@ -1913,7 +1915,8 @@ void DisplayServerOSX::mouse_set_mode(MouseMode p_mode) { return; } - WindowData &wd = windows[MAIN_WINDOW_ID]; + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + WindowData &wd = windows[window_id]; if (p_mode == MOUSE_MODE_CAPTURED) { // Apple Docs state that the display parameter is not used. // "This parameter is not used. By default, you may pass kCGDirectMainDisplay." @@ -1972,7 +1975,8 @@ void DisplayServerOSX::mouse_warp_to_position(const Point2i &p_to) { if (mouse_mode == MOUSE_MODE_CAPTURED) { last_mouse_pos = p_to; } else { - WindowData &wd = windows[MAIN_WINDOW_ID]; + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + WindowData &wd = windows[window_id]; //local point in window coords const NSRect contentRect = [wd.window_view frame]; @@ -3544,6 +3548,24 @@ DisplayServer::WindowID DisplayServerOSX::get_window_at_screen_position(const Po return INVALID_WINDOW_ID; } +int64_t DisplayServerOSX::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(!windows.has(p_window), 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return 0; // Not supported. + } + case WINDOW_HANDLE: { + return (int64_t)windows[p_window].window_object; + } + case WINDOW_VIEW: { + return (int64_t)windows[p_window].window_view; + } + default: { + return 0; + } + } +} + void DisplayServerOSX::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { _THREAD_SAFE_METHOD_ diff --git a/platform/osx/export/export_plugin.cpp b/platform/osx/export/export_plugin.cpp index 4d1f72f5c9..f0b58efb63 100644 --- a/platform/osx/export/export_plugin.cpp +++ b/platform/osx/export/export_plugin.cpp @@ -777,6 +777,24 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources"); } + Vector<String> translations = ProjectSettings::get_singleton()->get("internationalization/locale/translations"); + if (translations.size() > 0) { + { + String fname = tmp_app_path_name + "/Contents/Resources/en.lproj"; + tmp_app_dir->make_dir_recursive(fname); + FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + } + + for (const String &E : translations) { + Ref<Translation> tr = ResourceLoader::load(E); + if (tr.is_valid()) { + String fname = tmp_app_path_name + "/Contents/Resources/" + tr->get_locale() + ".lproj"; + tmp_app_dir->make_dir_recursive(fname); + FileAccessRef f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE); + } + } + } + // Now process our template. bool found_binary = false; Vector<String> dylibs_found; diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index cc7dd23770..74de8fb663 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -97,7 +97,10 @@ String DisplayServerWindows::get_name() const { void DisplayServerWindows::_set_mouse_mode_impl(MouseMode p_mode) { if (windows.has(MAIN_WINDOW_ID) && (p_mode == MOUSE_MODE_CAPTURED || p_mode == MOUSE_MODE_CONFINED || p_mode == MOUSE_MODE_CONFINED_HIDDEN)) { // Mouse is grabbed (captured or confined). - WindowData &wd = windows[MAIN_WINDOW_ID]; + + WindowID window_id = windows.has(last_focused_window) ? last_focused_window : MAIN_WINDOW_ID; + + WindowData &wd = windows[window_id]; RECT clipRect; GetClientRect(wd.hWnd, &clipRect); @@ -603,6 +606,24 @@ void DisplayServerWindows::gl_window_make_current(DisplayServer::WindowID p_wind #endif } +int64_t DisplayServerWindows::window_get_native_handle(HandleType p_handle_type, WindowID p_window) const { + ERR_FAIL_COND_V(!windows.has(p_window), 0); + switch (p_handle_type) { + case DISPLAY_HANDLE: { + return 0; // Not supported. + } + case WINDOW_HANDLE: { + return (int64_t)windows[p_window].hWnd; + } + case WINDOW_VIEW: { + return 0; // Not supported. + } + default: { + return 0; + } + } +} + void DisplayServerWindows::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { _THREAD_SAFE_METHOD_ @@ -721,6 +742,15 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi Vector2 ofs = window_get_position(p_window) - screen_get_position(window_get_current_screen(p_window)); window_set_position(ofs + screen_get_position(p_screen), p_window); } + + // Don't let the mouse leave the window when resizing to a smaller resolution. + if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { + RECT crect; + GetClientRect(wd.hWnd, &crect); + ClientToScreen(wd.hWnd, (POINT *)&crect.left); + ClientToScreen(wd.hWnd, (POINT *)&crect.right); + ClipCursor(&crect); + } } Point2i DisplayServerWindows::window_get_position(WindowID p_window) const { @@ -1083,6 +1113,15 @@ void DisplayServerWindows::window_set_mode(WindowMode p_mode, WindowID p_window) SystemParametersInfoA(SPI_SETMOUSETRAILS, 0, 0, 0); } } + + // Don't let the mouse leave the window when resizing to a smaller resolution. + if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) { + RECT crect; + GetClientRect(wd.hWnd, &crect); + ClientToScreen(wd.hWnd, (POINT *)&crect.left); + ClientToScreen(wd.hWnd, (POINT *)&crect.right); + ClipCursor(&crect); + } } DisplayServer::WindowMode DisplayServerWindows::window_get_mode(WindowID p_window) const { @@ -2643,98 +2682,72 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } } break; - case WM_MOVE: { - if (!IsIconic(windows[window_id].hWnd)) { - int x = int16_t(LOWORD(lParam)); - int y = int16_t(HIWORD(lParam)); - windows[window_id].last_pos = Point2(x, y); - - if (!windows[window_id].rect_changed_callback.is_null()) { - Variant size = Rect2i(windows[window_id].last_pos.x, windows[window_id].last_pos.y, windows[window_id].width, windows[window_id].height); - Variant *sizep = &size; - Variant ret; - Callable::CallError ce; - windows[window_id].rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce); + + case WM_WINDOWPOSCHANGED: { + Rect2i window_client_rect; + { + RECT rect; + GetClientRect(hWnd, &rect); + ClientToScreen(hWnd, (POINT *)&rect.left); + ClientToScreen(hWnd, (POINT *)&rect.right); + window_client_rect = Rect2i(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); + } + + WINDOWPOS *window_pos_params = (WINDOWPOS *)lParam; + WindowData &window = windows[window_id]; + + bool rect_changed = false; + if (!(window_pos_params->flags & SWP_NOSIZE) || window_pos_params->flags & SWP_FRAMECHANGED) { + int screen_id = window_get_current_screen(window_id); + Size2i screen_size = screen_get_size(screen_id); + Point2i screen_position = screen_get_position(screen_id); + + window.maximized = false; + window.minimized = false; + window.fullscreen = false; + + if (IsIconic(hWnd)) { + window.minimized = true; + } else if (IsZoomed(hWnd)) { + window.maximized = true; + } else if (window_client_rect.position == screen_position && window_client_rect.size == screen_size) { + window.fullscreen = true; } - } - } break; - case WM_SIZE: { - // Ignore window size change when a SIZE_MINIMIZED event is triggered. - if (wParam != SIZE_MINIMIZED) { - // The new width and height of the client area. - int window_w = LOWORD(lParam); - int window_h = HIWORD(lParam); - - // Set new value to the size if it isn't preserved. - if (window_w > 0 && window_h > 0 && !windows[window_id].preserve_window_size) { - windows[window_id].width = window_w; - windows[window_id].height = window_h; + + if (!window.minimized) { + window.width = window_client_rect.size.width; + window.height = window_client_rect.size.height; #if defined(VULKAN_ENABLED) if (context_vulkan && window_created) { - context_vulkan->window_resize(window_id, windows[window_id].width, windows[window_id].height); + context_vulkan->window_resize(window_id, window.width, window.height); } #endif + rect_changed = true; + } + } - } else { // If the size is preserved. - windows[window_id].preserve_window_size = false; + if (!window.minimized && (!(window_pos_params->flags & SWP_NOMOVE) || window_pos_params->flags & SWP_FRAMECHANGED)) { + window.last_pos = window_client_rect.position; + rect_changed = true; + } - // Restore the old size. - window_set_size(Size2(windows[window_id].width, windows[window_id].height), window_id); + if (rect_changed) { + if (!window.rect_changed_callback.is_null()) { + Variant size = Rect2i(window.last_pos.x, window.last_pos.y, window.width, window.height); + const Variant *args[] = { &size }; + Variant ret; + Callable::CallError ce; + window.rect_changed_callback.call(args, 1, ret, ce); } - } else { // When the window has been minimized, preserve its size. - windows[window_id].preserve_window_size = true; } - // Call windows rect change callback. - if (!windows[window_id].rect_changed_callback.is_null()) { - Variant size = Rect2i(windows[window_id].last_pos.x, windows[window_id].last_pos.y, windows[window_id].width, windows[window_id].height); - Variant *size_ptr = &size; - Variant ret; - Callable::CallError ce; - windows[window_id].rect_changed_callback.call((const Variant **)&size_ptr, 1, ret, ce); - } - - // The window has been maximized. - if (wParam == SIZE_MAXIMIZED) { - windows[window_id].maximized = true; - windows[window_id].minimized = false; - } - // The window has been minimized. - else if (wParam == SIZE_MINIMIZED) { - windows[window_id].maximized = false; - windows[window_id].minimized = true; - windows[window_id].preserve_window_size = false; - } - // The window has been resized, but neither the SIZE_MINIMIZED nor SIZE_MAXIMIZED value applies. - else if (wParam == SIZE_RESTORED) { - windows[window_id].maximized = false; - windows[window_id].minimized = false; - } -#if 0 - if (is_layered_allowed() && layered_window) { - DeleteObject(hBitmap); - - RECT r; - GetWindowRect(hWnd, &r); - dib_size = Size2i(r.right - r.left, r.bottom - r.top); - - BITMAPINFO bmi; - ZeroMemory(&bmi, sizeof(BITMAPINFO)); - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = dib_size.x; - bmi.bmiHeader.biHeight = dib_size.y; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; - bmi.bmiHeader.biCompression = BI_RGB; - bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4; - hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, nullptr, 0x0); - SelectObject(hDC_dib, hBitmap); - - ZeroMemory(dib_data, dib_size.x * dib_size.y * 4); - } -#endif + // Return here to prevent WM_MOVE and WM_SIZE from being sent + // See: https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-windowposchanged#remarks + return 0; + } break; + case WM_ENTERSIZEMOVE: { Input::get_singleton()->release_pressed_events(); windows[window_id].move_timer_id = SetTimer(windows[window_id].hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC) nullptr); @@ -2912,6 +2925,9 @@ void DisplayServerWindows::_process_activate_event(WindowID p_window_id, WPARAM alt_mem = false; control_mem = false; shift_mem = false; + + // Restore mouse mode. + _set_mouse_mode_impl(mouse_mode); } else { // WM_INACTIVE. Input::get_singleton()->release_pressed_events(); _send_window_event(windows[p_window_id], WINDOW_EVENT_FOCUS_OUT); diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index e86629ab6f..b73583b64a 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -326,7 +326,6 @@ class DisplayServerWindows : public DisplayServer { Vector<Vector2> mpath; - bool preserve_window_size = false; bool pre_fs_valid = false; RECT pre_fs_rect; bool maximized = false; @@ -473,6 +472,8 @@ public: virtual void show_window(WindowID p_window) override; virtual void delete_sub_window(WindowID p_window) override; + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; + 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) override; diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 68762db3a9..d30d0afc5c 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -76,8 +76,8 @@ void EditorExportPlatformWindows::get_export_options(List<ExportOption> *r_optio r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray())); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/icon", PROPERTY_HINT_FILE, "*.ico"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); - r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), "")); + r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_version", PROPERTY_HINT_PLACEHOLDER_TEXT, "1.0.0.0"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/company_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Company Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/product_name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Game Name"), "")); r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "application/file_description"), "")); @@ -89,6 +89,7 @@ void EditorExportPlatformWindows::_rcedit_add_data(const Ref<EditorExportPreset> String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); if (rcedit_path.is_empty()) { + WARN_PRINT("The rcedit tool is not configured in the Editor Settings (Export > Windows > Rcedit). No custom icon or app information data will be embedded in the exported executable."); return; } @@ -327,3 +328,46 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p return OK; } + +bool EditorExportPlatformWindows::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const { + String err = ""; + bool valid = EditorExportPlatformPC::can_export(p_preset, err, r_missing_templates); + + String rcedit_path = EditorSettings::get_singleton()->get("export/windows/rcedit"); + if (rcedit_path.is_empty()) { + err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > Rcedit) to change the icon or app information data.") + "\n"; + } + + String icon_path = ProjectSettings::get_singleton()->globalize_path(p_preset->get("application/icon")); + if (!icon_path.is_empty() && !FileAccess::exists(icon_path)) { + err += TTR("Invalid icon path:") + " " + icon_path + "\n"; + } + + // Only non-negative integers can exist in the version string. + + String file_version = p_preset->get("application/file_version"); + if (!file_version.is_empty()) { + PackedStringArray version_array = file_version.split(".", false); + if (version_array.size() != 4 || !version_array[0].is_valid_int() || + !version_array[1].is_valid_int() || !version_array[2].is_valid_int() || + !version_array[3].is_valid_int() || file_version.find("-") > -1) { + err += TTR("Invalid file version:") + " " + file_version + "\n"; + } + } + + String product_version = p_preset->get("application/product_version"); + if (!product_version.is_empty()) { + PackedStringArray version_array = product_version.split(".", false); + if (version_array.size() != 4 || !version_array[0].is_valid_int() || + !version_array[1].is_valid_int() || !version_array[2].is_valid_int() || + !version_array[3].is_valid_int() || product_version.find("-") > -1) { + err += TTR("Invalid product version:") + " " + product_version + "\n"; + } + } + + if (!err.is_empty()) { + r_error = err; + } + + return valid; +} diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 351333aa42..89e5b1b635 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -47,6 +47,7 @@ public: virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override; virtual void get_export_options(List<ExportOption> *r_options) override; virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; + virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; }; #endif diff --git a/platform/windows/godot_windows.cpp b/platform/windows/godot_windows.cpp index 7819ab9a32..618d5670d2 100644 --- a/platform/windows/godot_windows.cpp +++ b/platform/windows/godot_windows.cpp @@ -39,7 +39,7 @@ #ifndef TOOLS_ENABLED #if defined _MSC_VER #pragma section("pck", read) -__declspec(allocate("pck")) static char dummy[8] = { 0 }; +__declspec(allocate("pck")) static const char dummy[8] = { 0 }; #elif defined __GNUC__ static const char dummy[8] __attribute__((section("pck"), used)) = { 0 }; #endif @@ -140,6 +140,11 @@ int widechar_main(int argc, wchar_t **argv) { setlocale(LC_CTYPE, ""); +#ifndef TOOLS_ENABLED + // Workaround to prevent LTCG (MSVC LTO) from removing "pck" section + const char *dummy_guard = dummy; +#endif + char **argv_utf8 = new char *[argc]; for (int i = 0; i < argc; ++i) { diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 41ba1092db..d844531071 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -83,15 +83,23 @@ static String format_error_message(DWORD id) { return msg; } +void RedirectStream(const char *p_file_name, const char *p_mode, FILE *p_cpp_stream, const DWORD p_std_handle) { + const HANDLE h_existing = GetStdHandle(p_std_handle); + if (h_existing != INVALID_HANDLE_VALUE) { // Redirect only if attached console have a valid handle. + const HANDLE h_cpp = reinterpret_cast<HANDLE>(_get_osfhandle(_fileno(p_cpp_stream))); + if (h_cpp == INVALID_HANDLE_VALUE) { // Redirect only if it's not already redirected to the pipe or file. + FILE *fp = p_cpp_stream; + freopen_s(&fp, p_file_name, p_mode, p_cpp_stream); // Redirect stream. + setvbuf(p_cpp_stream, nullptr, _IONBF, 0); // Disable stream buffering. + } + } +} + void RedirectIOToConsole() { if (AttachConsole(ATTACH_PARENT_PROCESS)) { - FILE *fpstdin = stdin; - FILE *fpstdout = stdout; - FILE *fpstderr = stderr; - - freopen_s(&fpstdin, "CONIN$", "r", stdin); - freopen_s(&fpstdout, "CONOUT$", "w", stdout); - freopen_s(&fpstderr, "CONOUT$", "w", stderr); + RedirectStream("CONIN$", "r", stdin, STD_INPUT_HANDLE); + RedirectStream("CONOUT$", "w", stdout, STD_OUTPUT_HANDLE); + RedirectStream("CONOUT$", "w", stderr, STD_ERROR_HANDLE); printf("\n"); // Make sure our output is starting from the new line. } |