summaryrefslogtreecommitdiffstats
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/display_server_android.cpp2
-rw-r--r--platform/android/export/export_plugin.cpp2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java8
-rw-r--r--platform/android/java_godot_lib_jni.cpp2
-rw-r--r--platform/ios/app_delegate.mm2
-rw-r--r--platform/ios/display_server_ios.mm2
-rw-r--r--platform/ios/godot_ios.mm11
-rw-r--r--platform/linuxbsd/godot_linuxbsd.cpp13
-rw-r--r--platform/linuxbsd/wayland/display_server_wayland.cpp4
-rw-r--r--platform/linuxbsd/wayland/wayland_thread.cpp4
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp15
-rw-r--r--platform/macos/display_server_macos.h2
-rw-r--r--platform/macos/display_server_macos.mm15
-rw-r--r--platform/macos/godot_main_macos.mm19
-rw-r--r--platform/macos/native_menu_macos.h2
-rw-r--r--platform/macos/native_menu_macos.mm5
-rw-r--r--platform/web/detect.py2
-rw-r--r--platform/web/display_server_web.cpp2
-rw-r--r--platform/web/os_web.cpp4
-rw-r--r--platform/web/os_web.h1
-rw-r--r--platform/web/web_main.cpp16
-rw-r--r--platform/windows/display_server_windows.cpp37
-rw-r--r--platform/windows/display_server_windows.h12
-rw-r--r--platform/windows/godot_windows.cpp8
-rw-r--r--platform/windows/native_menu_windows.cpp24
-rw-r--r--platform/windows/native_menu_windows.h2
-rw-r--r--platform/windows/os_windows.cpp101
-rw-r--r--platform/windows/os_windows.h1
28 files changed, 251 insertions, 67 deletions
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 90759810b1..c6f2f82117 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -71,6 +71,8 @@ bool DisplayServerAndroid::has_feature(Feature p_feature) const {
case FEATURE_MOUSE:
//case FEATURE_MOUSE_WARP:
//case FEATURE_NATIVE_DIALOG:
+ //case FEATURE_NATIVE_DIALOG_INPUT:
+ //case FEATURE_NATIVE_DIALOG_FILE:
//case FEATURE_NATIVE_ICON:
//case FEATURE_WINDOW_TRANSPARENCY:
case FEATURE_CLIPBOARD:
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 894c13cc0b..64ef1397ba 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -3096,7 +3096,7 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
return err;
}
if (user_data.libs.size() > 0) {
- Ref<FileAccess> fa = FileAccess::open(GDEXTENSION_LIBS_PATH, FileAccess::WRITE);
+ Ref<FileAccess> fa = FileAccess::open(gdextension_libs_path, FileAccess::WRITE);
fa->store_string(JSON::stringify(user_data.libs, "\t"));
}
} else {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
index 9a6b6d5037..9df890e6bd 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/utils/PermissionsUtil.java
@@ -293,15 +293,15 @@ public final class PermissionsUtil {
/**
* Returns the permissions defined in the AndroidManifest.xml file.
* @param context the caller context for this method.
- * @return manifest permissions list
+ * @return mutable copy of manifest permissions list
* @throws PackageManager.NameNotFoundException the exception is thrown when a given package, application, or component name cannot be found.
*/
- public static List<String> getManifestPermissions(Context context) throws PackageManager.NameNotFoundException {
+ public static ArrayList<String> getManifestPermissions(Context context) throws PackageManager.NameNotFoundException {
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS);
if (packageInfo.requestedPermissions == null)
- return Collections.emptyList();
- return Arrays.asList(packageInfo.requestedPermissions);
+ return new ArrayList<String>();
+ return new ArrayList<>(Arrays.asList(packageInfo.requestedPermissions));
}
/**
diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp
index 85d5cf2796..2215f706c5 100644
--- a/platform/android/java_godot_lib_jni.cpp
+++ b/platform/android/java_godot_lib_jni.cpp
@@ -250,7 +250,7 @@ JNIEXPORT jboolean JNICALL Java_org_godotengine_godot_GodotLib_step(JNIEnv *env,
}
if (step.get() == 1) {
- if (!Main::start()) {
+ if (Main::start() != EXIT_SUCCESS) {
return true; // should exit instead and print the error
}
diff --git a/platform/ios/app_delegate.mm b/platform/ios/app_delegate.mm
index 5a0c57be93..37d2696434 100644
--- a/platform/ios/app_delegate.mm
+++ b/platform/ios/app_delegate.mm
@@ -116,6 +116,8 @@ static ViewController *mainViewController = nil;
} else if (sessionCategorySetting == SESSION_CATEGORY_PLAY_AND_RECORD) {
category = AVAudioSessionCategoryPlayAndRecord;
options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
+ options |= AVAudioSessionCategoryOptionAllowBluetoothA2DP;
+ options |= AVAudioSessionCategoryOptionAllowAirPlay;
} else if (sessionCategorySetting == SESSION_CATEGORY_PLAYBACK) {
category = AVAudioSessionCategoryPlayback;
} else if (sessionCategorySetting == SESSION_CATEGORY_RECORD) {
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index e1c3dcd372..f84fb01ad0 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -328,6 +328,8 @@ bool DisplayServerIOS::has_feature(Feature p_feature) const {
// case FEATURE_MOUSE:
// case FEATURE_MOUSE_WARP:
// case FEATURE_NATIVE_DIALOG:
+ // case FEATURE_NATIVE_DIALOG_INPUT:
+ // case FEATURE_NATIVE_DIALOG_FILE:
// case FEATURE_NATIVE_ICON:
// case FEATURE_WINDOW_TRANSPARENCY:
case FEATURE_CLIPBOARD:
diff --git a/platform/ios/godot_ios.mm b/platform/ios/godot_ios.mm
index 5e66c8b47b..9d35d43344 100644
--- a/platform/ios/godot_ios.mm
+++ b/platform/ios/godot_ios.mm
@@ -102,15 +102,16 @@ int ios_main(int argc, char **argv) {
Error err = Main::setup(fargv[0], argc - 1, &fargv[1], false);
- if (err == ERR_HELP) { // Returned by --help and --version, so success.
- return 0;
- } else if (err != OK) {
- return 255;
+ if (err != OK) {
+ if (err == ERR_HELP) { // Returned by --help and --version, so success.
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
}
os->initialize_modules();
- return 0;
+ return os->get_exit_code();
}
void ios_finish() {
diff --git a/platform/linuxbsd/godot_linuxbsd.cpp b/platform/linuxbsd/godot_linuxbsd.cpp
index a2b6fbeb25..b0880c86b8 100644
--- a/platform/linuxbsd/godot_linuxbsd.cpp
+++ b/platform/linuxbsd/godot_linuxbsd.cpp
@@ -72,18 +72,19 @@ int main(int argc, char *argv[]) {
char *ret = getcwd(cwd, PATH_MAX);
Error err = Main::setup(argv[0], argc - 1, &argv[1]);
+
if (err != OK) {
free(cwd);
-
if (err == ERR_HELP) { // Returned by --help and --version, so success.
- return 0;
+ return EXIT_SUCCESS;
}
- return 255;
+ return EXIT_FAILURE;
}
- if (Main::start()) {
- os.set_exit_code(EXIT_SUCCESS);
- os.run(); // it is actually the OS that decides how to run
+ if (Main::start() == EXIT_SUCCESS) {
+ os.run();
+ } else {
+ os.set_exit_code(EXIT_FAILURE);
}
Main::cleanup();
diff --git a/platform/linuxbsd/wayland/display_server_wayland.cpp b/platform/linuxbsd/wayland/display_server_wayland.cpp
index 80b6029c9d..d00d5deb2c 100644
--- a/platform/linuxbsd/wayland/display_server_wayland.cpp
+++ b/platform/linuxbsd/wayland/display_server_wayland.cpp
@@ -210,8 +210,10 @@ bool DisplayServerWayland::has_feature(Feature p_feature) const {
return true;
} break;
+ //case FEATURE_NATIVE_DIALOG:
+ //case FEATURE_NATIVE_DIALOG_INPUT:
#ifdef DBUS_ENABLED
- case FEATURE_NATIVE_DIALOG: {
+ case FEATURE_NATIVE_DIALOG_FILE: {
return true;
} break;
#endif
diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp
index 5040f5dd45..7f9008e952 100644
--- a/platform/linuxbsd/wayland/wayland_thread.cpp
+++ b/platform/linuxbsd/wayland/wayland_thread.cpp
@@ -1563,7 +1563,7 @@ void WaylandThread::_wl_pointer_on_frame(void *data, struct wl_pointer *wl_point
}
if (old_pd.pressed_button_mask != pd.pressed_button_mask) {
- BitField<MouseButtonMask> pressed_mask_delta = BitField<MouseButtonMask>((uint32_t)old_pd.pressed_button_mask ^ (uint32_t)pd.pressed_button_mask);
+ BitField<MouseButtonMask> pressed_mask_delta = old_pd.pressed_button_mask ^ pd.pressed_button_mask;
const MouseButton buttons_to_test[] = {
MouseButton::LEFT,
@@ -2454,7 +2454,7 @@ void WaylandThread::_wp_tablet_tool_on_frame(void *data, struct zwp_tablet_tool_
mm->set_relative_screen_position(mm->get_relative());
Vector2i pos_delta = td.position - old_td.position;
- uint32_t time_delta = td.motion_time - td.motion_time;
+ uint32_t time_delta = td.motion_time - old_td.motion_time;
mm->set_velocity((Vector2)pos_delta / time_delta);
Ref<InputEventMessage> inputev_msg;
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 34aa15abbb..9069dd423f 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -128,8 +128,10 @@ bool DisplayServerX11::has_feature(Feature p_feature) const {
//case FEATURE_HIDPI:
case FEATURE_ICON:
#ifdef DBUS_ENABLED
- case FEATURE_NATIVE_DIALOG:
+ case FEATURE_NATIVE_DIALOG_FILE:
#endif
+ //case FEATURE_NATIVE_DIALOG:
+ //case FEATURE_NATIVE_DIALOG_INPUT:
//case FEATURE_NATIVE_ICON:
case FEATURE_SWAP_BUFFERS:
#ifdef DBUS_ENABLED
@@ -1995,8 +1997,7 @@ void DisplayServerX11::window_set_current_screen(int p_screen, WindowID p_window
Size2i wsize = window_get_size(p_window);
wpos += srect.position;
if (srect != Rect2i()) {
- wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - wsize.width / 3);
- wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
+ wpos = wpos.clamp(srect.position, srect.position + srect.size - wsize / 3);
}
window_set_position(wpos, p_window);
}
@@ -2224,8 +2225,7 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
Size2i size = p_size;
- size.x = MAX(1, size.x);
- size.y = MAX(1, size.y);
+ size = size.max(Size2i(1, 1));
WindowData &wd = windows[p_window];
@@ -5212,7 +5212,7 @@ void DisplayServerX11::set_icon(const Ref<Image> &p_icon) {
if (g_set_icon_error) {
g_set_icon_error = false;
- WARN_PRINT("Icon too large, attempting to resize icon.");
+ WARN_PRINT(vformat("Icon too large (%dx%d), attempting to downscale icon.", w, h));
int new_width, new_height;
if (w > h) {
@@ -5451,8 +5451,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
} else {
Rect2i srect = screen_get_usable_rect(rq_screen);
Point2i wpos = p_rect.position;
- wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
- wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
+ wpos = wpos.clamp(srect.position, srect.position + srect.size - p_rect.size / 3);
win_rect.position = wpos;
}
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 09073a8030..7c9d073afc 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -241,6 +241,8 @@ public:
NSImage *_convert_to_nsimg(Ref<Image> &p_image) const;
Point2i _get_screens_origin() const;
+ void set_menu_delegate(NSMenu *p_menu);
+
void send_event(NSEvent *p_event);
void send_window_event(const WindowData &p_wd, WindowEvent p_event);
void release_pressed_events();
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index c52ed00b3d..d06eab8531 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -83,8 +83,7 @@ DisplayServerMacOS::WindowID DisplayServerMacOS::_create_window(WindowMode p_mod
Rect2i srect = screen_get_usable_rect(rq_screen);
Point2i wpos = p_rect.position;
if (srect != Rect2i()) {
- wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
- wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
+ wpos = wpos.clamp(srect.position, srect.position + srect.size - p_rect.size / 3);
}
// macOS native y-coordinate relative to _get_screens_origin() is negative,
// Godot passes a positive value.
@@ -291,6 +290,10 @@ void DisplayServerMacOS::_update_displays_arrangement() {
displays_arrangement_dirty = false;
}
+void DisplayServerMacOS::set_menu_delegate(NSMenu *p_menu) {
+ [p_menu setDelegate:menu_delegate];
+}
+
Point2i DisplayServerMacOS::_get_screens_origin() const {
// Returns the native top-left screen coordinate of the smallest rectangle
// that encompasses all screens. Needed in get_screen_position(),
@@ -756,6 +759,8 @@ bool DisplayServerMacOS::has_feature(Feature p_feature) const {
case FEATURE_CURSOR_SHAPE:
case FEATURE_CUSTOM_CURSOR_SHAPE:
case FEATURE_NATIVE_DIALOG:
+ case FEATURE_NATIVE_DIALOG_INPUT:
+ case FEATURE_NATIVE_DIALOG_FILE:
case FEATURE_IME:
case FEATURE_WINDOW_TRANSPARENCY:
case FEATURE_HIDPI:
@@ -1877,8 +1882,7 @@ void DisplayServerMacOS::window_set_current_screen(int p_screen, WindowID p_wind
Size2i wsize = window_get_size(p_window);
wpos += srect.position;
- wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - wsize.width / 3);
- wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
+ wpos = wpos.clamp(srect.position, srect.position + srect.size - wsize / 3);
window_set_position(wpos, p_window);
if (was_fullscreen) {
@@ -2309,8 +2313,7 @@ void DisplayServerMacOS::window_set_window_buttons_offset(const Vector2i &p_offs
WindowData &wd = windows[p_window];
float scale = screen_get_max_scale();
wd.wb_offset = p_offset / scale;
- wd.wb_offset.x = MAX(wd.wb_offset.x, 12);
- wd.wb_offset.y = MAX(wd.wb_offset.y, 12);
+ wd.wb_offset = wd.wb_offset.max(Vector2i(12, 12));
if (wd.window_button_view) {
[wd.window_button_view setOffset:NSMakePoint(wd.wb_offset.x, wd.wb_offset.y)];
}
diff --git a/platform/macos/godot_main_macos.mm b/platform/macos/godot_main_macos.mm
index 3959fb686c..942c351ac0 100644
--- a/platform/macos/godot_main_macos.mm
+++ b/platform/macos/godot_main_macos.mm
@@ -69,18 +69,21 @@ int main(int argc, char **argv) {
err = Main::setup(argv[0], argc - first_arg, &argv[first_arg]);
}
- if (err == ERR_HELP) { // Returned by --help and --version, so success.
- return 0;
- } else if (err != OK) {
- return 255;
+ if (err != OK) {
+ if (err == ERR_HELP) { // Returned by --help and --version, so success.
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
}
- bool ok;
+ int ret;
@autoreleasepool {
- ok = Main::start();
+ ret = Main::start();
}
- if (ok) {
- os.run(); // It is actually the OS that decides how to run.
+ if (ret == EXIT_SUCCESS) {
+ os.run();
+ } else {
+ os.set_exit_code(EXIT_FAILURE);
}
@autoreleasepool {
diff --git a/platform/macos/native_menu_macos.h b/platform/macos/native_menu_macos.h
index c00a510fd5..1d9feb64a7 100644
--- a/platform/macos/native_menu_macos.h
+++ b/platform/macos/native_menu_macos.h
@@ -33,7 +33,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/rid_owner.h"
-#include "servers/native_menu.h"
+#include "servers/display/native_menu.h"
#import <AppKit/AppKit.h>
#import <ApplicationServices/ApplicationServices.h>
diff --git a/platform/macos/native_menu_macos.mm b/platform/macos/native_menu_macos.mm
index 250b64dc04..8c2dd98862 100644
--- a/platform/macos/native_menu_macos.mm
+++ b/platform/macos/native_menu_macos.mm
@@ -223,6 +223,11 @@ RID NativeMenuMacOS::get_system_menu(SystemMenus p_menu_id) const {
RID NativeMenuMacOS::create_menu() {
MenuData *md = memnew(MenuData);
md->menu = [[NSMenu alloc] initWithTitle:@""];
+ [md->menu setAutoenablesItems:NO];
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
+ if (ds) {
+ ds->set_menu_delegate(md->menu);
+ }
RID rid = menus.make_rid(md);
menu_lookup[md->menu] = rid;
return rid;
diff --git a/platform/web/detect.py b/platform/web/detect.py
index e692c79a20..2d2cc288a1 100644
--- a/platform/web/detect.py
+++ b/platform/web/detect.py
@@ -86,7 +86,7 @@ def configure(env: "SConsEnvironment"):
supported_arches = ["wasm32"]
if env["arch"] not in supported_arches:
print(
- 'Unsupported CPU architecture "%s" for iOS. Supported architectures are: %s.'
+ 'Unsupported CPU architecture "%s" for Web. Supported architectures are: %s.'
% (env["arch"], ", ".join(supported_arches))
)
sys.exit()
diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp
index 281f312000..06f5eb82f7 100644
--- a/platform/web/display_server_web.cpp
+++ b/platform/web/display_server_web.cpp
@@ -1128,6 +1128,8 @@ bool DisplayServerWeb::has_feature(Feature p_feature) const {
return true;
//case FEATURE_MOUSE_WARP:
//case FEATURE_NATIVE_DIALOG:
+ //case FEATURE_NATIVE_DIALOG_INPUT:
+ //case FEATURE_NATIVE_DIALOG_FILE:
//case FEATURE_NATIVE_ICON:
//case FEATURE_WINDOW_TRANSPARENCY:
//case FEATURE_KEEP_SCREEN_ON:
diff --git a/platform/web/os_web.cpp b/platform/web/os_web.cpp
index 45671ca491..4b93ce9e75 100644
--- a/platform/web/os_web.cpp
+++ b/platform/web/os_web.cpp
@@ -105,6 +105,10 @@ Error OS_Web::execute(const String &p_path, const List<String> &p_arguments, Str
return create_process(p_path, p_arguments);
}
+Dictionary OS_Web::execute_with_pipe(const String &p_path, const List<String> &p_arguments) {
+ ERR_FAIL_V_MSG(Dictionary(), "OS::execute_with_pipe is not available on the Web platform.");
+}
+
Error OS_Web::create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id, bool p_open_console) {
Array args;
for (const String &E : p_arguments) {
diff --git a/platform/web/os_web.h b/platform/web/os_web.h
index e578c93925..16f8ea8550 100644
--- a/platform/web/os_web.h
+++ b/platform/web/os_web.h
@@ -80,6 +80,7 @@ public:
bool main_loop_iterate();
Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) override;
+ Dictionary execute_with_pipe(const String &p_path, const List<String> &p_arguments) override;
Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
Error kill(const ProcessID &p_pid) override;
int get_process_id() const override;
diff --git a/platform/web/web_main.cpp b/platform/web/web_main.cpp
index ad2a801881..04513f6d57 100644
--- a/platform/web/web_main.cpp
+++ b/platform/web/web_main.cpp
@@ -109,24 +109,22 @@ extern EMSCRIPTEN_KEEPALIVE int godot_web_main(int argc, char *argv[]) {
// Proper shutdown in case of setup failure.
if (err != OK) {
- int exit_code = (int)err;
- if (err == ERR_HELP) {
- exit_code = 0; // Called with --help.
- }
- os->set_exit_code(exit_code);
// Will only exit after sync.
emscripten_set_main_loop(exit_callback, -1, false);
godot_js_os_finish_async(cleanup_after_sync);
- return exit_code;
+ if (err == ERR_HELP) { // Returned by --help and --version, so success.
+ return EXIT_SUCCESS;
+ }
+ return EXIT_FAILURE;
}
- os->set_exit_code(0);
main_started = true;
// Ease up compatibility.
ResourceLoader::set_abort_on_missing_resources(false);
- Main::start();
+ int ret = Main::start();
+ os->set_exit_code(ret);
os->get_main_loop()->initialize();
#ifdef TOOLS_ENABLED
if (Engine::get_singleton()->is_project_manager_hint() && FileAccess::exists("/tmp/preload.zip")) {
@@ -140,5 +138,5 @@ extern EMSCRIPTEN_KEEPALIVE int godot_web_main(int argc, char *argv[]) {
// We are inside an animation frame, we want to immediately draw on the newly setup canvas.
main_loop_callback();
- return 0;
+ return os->get_exit_code();
}
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index 2093f552ce..e540b7617f 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -114,6 +114,8 @@ bool DisplayServerWindows::has_feature(Feature p_feature) const {
case FEATURE_ICON:
case FEATURE_NATIVE_ICON:
case FEATURE_NATIVE_DIALOG:
+ case FEATURE_NATIVE_DIALOG_INPUT:
+ case FEATURE_NATIVE_DIALOG_FILE:
case FEATURE_SWAP_BUFFERS:
case FEATURE_KEEP_SCREEN_ON:
case FEATURE_TEXT_TO_SPEECH:
@@ -903,8 +905,7 @@ static BOOL CALLBACK _MonitorEnumProcPos(HMONITOR hMonitor, HDC hdcMonitor, LPRE
static BOOL CALLBACK _MonitorEnumProcOrigin(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) {
EnumPosData *data = (EnumPosData *)dwData;
- data->pos.x = MIN(data->pos.x, lprcMonitor->left);
- data->pos.y = MIN(data->pos.y, lprcMonitor->top);
+ data->pos = data->pos.min(Point2(lprcMonitor->left, lprcMonitor->top));
return TRUE;
}
@@ -1637,8 +1638,7 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi
Size2i wsize = window_get_size(p_window);
wpos += srect.position;
- wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - wsize.width / 3);
- wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
+ wpos = wpos.clamp(srect.position, srect.position + srect.size - wsize / 3);
window_set_position(wpos, p_window);
}
}
@@ -5076,8 +5076,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
Rect2i srect = screen_get_usable_rect(rq_screen);
Point2i wpos = p_rect.position;
if (srect != Rect2i()) {
- wpos.x = CLAMP(wpos.x, srect.position.x, srect.position.x + srect.size.width - p_rect.size.width / 3);
- wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - p_rect.size.height / 3);
+ wpos = wpos.clamp(srect.position, srect.position + srect.size - p_rect.size / 3);
}
WindowRect.left = wpos.x;
@@ -5497,6 +5496,32 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
GetImmersiveColorFromColorSetEx = (GetImmersiveColorFromColorSetExPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(95));
GetImmersiveColorTypeFromName = (GetImmersiveColorTypeFromNamePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(96));
GetImmersiveUserColorSetPreference = (GetImmersiveUserColorSetPreferencePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(98));
+ if (os_ver.dwBuildNumber >= 17763) {
+ AllowDarkModeForAppPtr AllowDarkModeForApp = nullptr;
+ SetPreferredAppModePtr SetPreferredAppMode = nullptr;
+ FlushMenuThemesPtr FlushMenuThemes = nullptr;
+ if (os_ver.dwBuildNumber < 18362) {
+ AllowDarkModeForApp = (AllowDarkModeForAppPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(135));
+ } else {
+ SetPreferredAppMode = (SetPreferredAppModePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(135));
+ FlushMenuThemes = (FlushMenuThemesPtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(136));
+ }
+ RefreshImmersiveColorPolicyStatePtr RefreshImmersiveColorPolicyState = (RefreshImmersiveColorPolicyStatePtr)GetProcAddress(ux_theme_lib, MAKEINTRESOURCEA(104));
+ if (ShouldAppsUseDarkMode) {
+ bool dark_mode = ShouldAppsUseDarkMode();
+ if (SetPreferredAppMode) {
+ SetPreferredAppMode(dark_mode ? APPMODE_ALLOWDARK : APPMODE_DEFAULT);
+ } else if (AllowDarkModeForApp) {
+ AllowDarkModeForApp(dark_mode);
+ }
+ if (RefreshImmersiveColorPolicyState) {
+ RefreshImmersiveColorPolicyState();
+ }
+ if (FlushMenuThemes) {
+ FlushMenuThemes();
+ }
+ }
+ }
ux_theme_available = ShouldAppsUseDarkMode && GetImmersiveColorFromColorSetEx && GetImmersiveColorTypeFromName && GetImmersiveUserColorSetPreference;
if (os_ver.dwBuildNumber >= 18363) {
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index 910b9baa45..1191f22968 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -154,11 +154,23 @@ typedef UINT(WINAPI *WTInfoPtr)(UINT p_category, UINT p_index, LPVOID p_output);
typedef BOOL(WINAPI *WTPacketPtr)(HANDLE p_ctx, UINT p_param, LPVOID p_packets);
typedef BOOL(WINAPI *WTEnablePtr)(HANDLE p_ctx, BOOL p_enable);
+enum PreferredAppMode {
+ APPMODE_DEFAULT = 0,
+ APPMODE_ALLOWDARK = 1,
+ APPMODE_FORCEDARK = 2,
+ APPMODE_FORCELIGHT = 3,
+ APPMODE_MAX = 4
+};
+
typedef bool(WINAPI *ShouldAppsUseDarkModePtr)();
typedef DWORD(WINAPI *GetImmersiveColorFromColorSetExPtr)(UINT dwImmersiveColorSet, UINT dwImmersiveColorType, bool bIgnoreHighContrast, UINT dwHighContrastCacheMode);
typedef int(WINAPI *GetImmersiveColorTypeFromNamePtr)(const WCHAR *name);
typedef int(WINAPI *GetImmersiveUserColorSetPreferencePtr)(bool bForceCheckRegistry, bool bSkipCheckOnFail);
typedef HRESULT(WINAPI *RtlGetVersionPtr)(OSVERSIONINFOW *lpVersionInformation);
+typedef bool(WINAPI *AllowDarkModeForAppPtr)(bool darkMode);
+typedef PreferredAppMode(WINAPI *SetPreferredAppModePtr)(PreferredAppMode appMode);
+typedef void(WINAPI *RefreshImmersiveColorPolicyStatePtr)();
+typedef void(WINAPI *FlushMenuThemesPtr)();
// Windows Ink API
#ifndef POINTER_STRUCTURES
diff --git a/platform/windows/godot_windows.cpp b/platform/windows/godot_windows.cpp
index f86ecd87fb..5f41b4e568 100644
--- a/platform/windows/godot_windows.cpp
+++ b/platform/windows/godot_windows.cpp
@@ -171,13 +171,15 @@ int widechar_main(int argc, wchar_t **argv) {
delete[] argv_utf8;
if (err == ERR_HELP) { // Returned by --help and --version, so success.
- return 0;
+ return EXIT_SUCCESS;
}
- return 255;
+ return EXIT_FAILURE;
}
- if (Main::start()) {
+ if (Main::start() == EXIT_SUCCESS) {
os.run();
+ } else {
+ os.set_exit_code(EXIT_FAILURE);
}
Main::cleanup();
diff --git a/platform/windows/native_menu_windows.cpp b/platform/windows/native_menu_windows.cpp
index 13d1cc2a67..40a08f87df 100644
--- a/platform/windows/native_menu_windows.cpp
+++ b/platform/windows/native_menu_windows.cpp
@@ -141,7 +141,7 @@ RID NativeMenuWindows::create_menu() {
ZeroMemory(&menu_info, sizeof(menu_info));
menu_info.cbSize = sizeof(menu_info);
menu_info.fMask = MIM_STYLE;
- menu_info.dwStyle = MNS_NOTIFYBYPOS | MNS_MODELESS;
+ menu_info.dwStyle = MNS_NOTIFYBYPOS;
SetMenuInfo(md->menu, &menu_info);
RID rid = menus.make_rid(md);
@@ -189,7 +189,9 @@ void NativeMenuWindows::popup(const RID &p_rid, const Vector2i &p_position) {
if (md->is_rtl) {
flags |= TPM_LAYOUTRTL;
}
+ SetForegroundWindow(hwnd);
TrackPopupMenuEx(md->menu, flags, p_position.x, p_position.y, hwnd, nullptr);
+ PostMessage(hwnd, WM_NULL, 0, 0);
}
void NativeMenuWindows::set_interface_direction(const RID &p_rid, bool p_is_rtl) {
@@ -556,9 +558,16 @@ int NativeMenuWindows::find_item_index_with_text(const RID &p_rid, const String
ZeroMemory(&item, sizeof(item));
item.cbSize = sizeof(item);
item.fMask = MIIM_STRING;
+ item.dwTypeData = nullptr;
if (GetMenuItemInfoW(md->menu, i, true, &item)) {
- if (String::utf16((const char16_t *)item.dwTypeData) == p_text) {
- return i;
+ item.cch++;
+ Char16String str;
+ str.resize(item.cch);
+ item.dwTypeData = (LPWSTR)str.ptrw();
+ if (GetMenuItemInfoW(md->menu, i, true, &item)) {
+ if (String::utf16((const char16_t *)str.get_data()) == p_text) {
+ return i;
+ }
}
}
}
@@ -700,8 +709,15 @@ String NativeMenuWindows::get_item_text(const RID &p_rid, int p_idx) const {
ZeroMemory(&item, sizeof(item));
item.cbSize = sizeof(item);
item.fMask = MIIM_STRING;
+ item.dwTypeData = nullptr;
if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
- return String::utf16((const char16_t *)item.dwTypeData);
+ item.cch++;
+ Char16String str;
+ str.resize(item.cch);
+ item.dwTypeData = (LPWSTR)str.ptrw();
+ if (GetMenuItemInfoW(md->menu, p_idx, true, &item)) {
+ return String::utf16((const char16_t *)str.get_data());
+ }
}
return String();
}
diff --git a/platform/windows/native_menu_windows.h b/platform/windows/native_menu_windows.h
index 6eab56d8b6..74fd231903 100644
--- a/platform/windows/native_menu_windows.h
+++ b/platform/windows/native_menu_windows.h
@@ -33,7 +33,7 @@
#include "core/templates/hash_map.h"
#include "core/templates/rid_owner.h"
-#include "servers/native_menu.h"
+#include "servers/display/native_menu.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 152b9ac10f..c39b327953 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -42,6 +42,7 @@
#include "drivers/unix/net_socket_posix.h"
#include "drivers/windows/dir_access_windows.h"
#include "drivers/windows/file_access_windows.h"
+#include "drivers/windows/file_access_windows_pipe.h"
#include "main/main.h"
#include "servers/audio_server.h"
#include "servers/rendering/rendering_server_default.h"
@@ -178,6 +179,7 @@ void OS_Windows::initialize() {
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_RESOURCES);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_USERDATA);
FileAccess::make_default<FileAccessWindows>(FileAccess::ACCESS_FILESYSTEM);
+ FileAccess::make_default<FileAccessWindowsPipe>(FileAccess::ACCESS_PIPE);
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_RESOURCES);
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_USERDATA);
DirAccess::make_default<DirAccessWindows>(DirAccess::ACCESS_FILESYSTEM);
@@ -727,6 +729,105 @@ Dictionary OS_Windows::get_memory_info() const {
return meminfo;
}
+Dictionary OS_Windows::execute_with_pipe(const String &p_path, const List<String> &p_arguments) {
+#define CLEAN_PIPES \
+ if (pipe_in[0] != 0) { \
+ CloseHandle(pipe_in[0]); \
+ } \
+ if (pipe_in[1] != 0) { \
+ CloseHandle(pipe_in[1]); \
+ } \
+ if (pipe_out[0] != 0) { \
+ CloseHandle(pipe_out[0]); \
+ } \
+ if (pipe_out[1] != 0) { \
+ CloseHandle(pipe_out[1]); \
+ } \
+ if (pipe_err[0] != 0) { \
+ CloseHandle(pipe_err[0]); \
+ } \
+ if (pipe_err[1] != 0) { \
+ CloseHandle(pipe_err[1]); \
+ }
+
+ Dictionary ret;
+
+ String path = p_path.replace("/", "\\");
+ String command = _quote_command_line_argument(path);
+ for (const String &E : p_arguments) {
+ command += " " + _quote_command_line_argument(E);
+ }
+
+ // Create pipes.
+ HANDLE pipe_in[2] = { 0, 0 };
+ HANDLE pipe_out[2] = { 0, 0 };
+ HANDLE pipe_err[2] = { 0, 0 };
+
+ SECURITY_ATTRIBUTES sa;
+ sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+ sa.bInheritHandle = true;
+ sa.lpSecurityDescriptor = nullptr;
+
+ ERR_FAIL_COND_V(!CreatePipe(&pipe_in[0], &pipe_in[1], &sa, 0), ret);
+ if (!SetHandleInformation(pipe_in[1], HANDLE_FLAG_INHERIT, 0)) {
+ CLEAN_PIPES
+ ERR_FAIL_V(ret);
+ }
+ if (!CreatePipe(&pipe_out[0], &pipe_out[1], &sa, 0)) {
+ CLEAN_PIPES
+ ERR_FAIL_V(ret);
+ }
+ if (!SetHandleInformation(pipe_out[0], HANDLE_FLAG_INHERIT, 0)) {
+ CLEAN_PIPES
+ ERR_FAIL_V(ret);
+ }
+ if (!CreatePipe(&pipe_err[0], &pipe_err[1], &sa, 0)) {
+ CLEAN_PIPES
+ ERR_FAIL_V(ret);
+ }
+ ERR_FAIL_COND_V(!SetHandleInformation(pipe_err[0], HANDLE_FLAG_INHERIT, 0), ret);
+
+ // Create process.
+ ProcessInfo pi;
+ ZeroMemory(&pi.si, sizeof(pi.si));
+ pi.si.cb = sizeof(pi.si);
+ ZeroMemory(&pi.pi, sizeof(pi.pi));
+ LPSTARTUPINFOW si_w = (LPSTARTUPINFOW)&pi.si;
+
+ pi.si.dwFlags |= STARTF_USESTDHANDLES;
+ pi.si.hStdInput = pipe_in[0];
+ pi.si.hStdOutput = pipe_out[1];
+ pi.si.hStdError = pipe_err[1];
+
+ DWORD creation_flags = NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW;
+
+ if (!CreateProcessW(nullptr, (LPWSTR)(command.utf16().ptrw()), nullptr, nullptr, true, creation_flags, nullptr, nullptr, si_w, &pi.pi)) {
+ CLEAN_PIPES
+ ERR_FAIL_V_MSG(ret, "Could not create child process: " + command);
+ }
+ CloseHandle(pipe_in[0]);
+ CloseHandle(pipe_out[1]);
+ CloseHandle(pipe_err[1]);
+
+ ProcessID pid = pi.pi.dwProcessId;
+ process_map->insert(pid, pi);
+
+ Ref<FileAccessWindowsPipe> main_pipe;
+ main_pipe.instantiate();
+ main_pipe->open_existing(pipe_out[0], pipe_in[1]);
+
+ Ref<FileAccessWindowsPipe> err_pipe;
+ err_pipe.instantiate();
+ err_pipe->open_existing(pipe_err[0], 0);
+
+ ret["stdio"] = main_pipe;
+ ret["stderr"] = err_pipe;
+ ret["pid"] = pid;
+
+#undef CLEAN_PIPES
+ return ret;
+}
+
Error OS_Windows::execute(const String &p_path, const List<String> &p_arguments, String *r_pipe, int *r_exitcode, bool read_stderr, Mutex *p_pipe_mutex, bool p_open_console) {
String path = p_path.replace("/", "\\");
String command = _quote_command_line_argument(path);
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 351cb32c9b..c703a3ddca 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -181,6 +181,7 @@ public:
virtual Dictionary get_memory_info() const override;
virtual Error execute(const String &p_path, const List<String> &p_arguments, String *r_pipe = nullptr, int *r_exitcode = nullptr, bool read_stderr = false, Mutex *p_pipe_mutex = nullptr, bool p_open_console = false) override;
+ virtual Dictionary execute_with_pipe(const String &p_path, const List<String> &p_arguments) override;
virtual Error create_process(const String &p_path, const List<String> &p_arguments, ProcessID *r_child_id = nullptr, bool p_open_console = false) override;
virtual Error kill(const ProcessID &p_pid) override;
virtual int get_process_id() const override;