summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
Diffstat (limited to 'platform')
-rw-r--r--platform/android/export/export_plugin.cpp50
-rw-r--r--platform/android/export/gradle_export_util.cpp30
-rw-r--r--platform/android/export/gradle_export_util.h2
-rw-r--r--platform/android/java/app/AndroidManifest.xml21
-rw-r--r--platform/android/java/lib/AndroidManifest.xml10
-rw-r--r--platform/android/java/lib/res/xml/godot_provider_paths.xml11
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java2
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java38
-rw-r--r--platform/linuxbsd/os_linuxbsd.cpp6
-rw-r--r--platform/linuxbsd/x11/display_server_x11.cpp19
-rw-r--r--platform/macos/display_server_macos.mm18
-rw-r--r--platform/windows/display_server_windows.cpp85
12 files changed, 166 insertions, 126 deletions
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 9ebb8aa102..c02acbee83 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -899,10 +899,6 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
bool screen_support_large = p_preset->get("screen/support_large");
bool screen_support_xlarge = p_preset->get("screen/support_xlarge");
- int xr_mode_index = p_preset->get("xr_features/xr_mode");
- int hand_tracking_index = p_preset->get("xr_features/hand_tracking");
- int hand_tracking_frequency_index = p_preset->get("xr_features/hand_tracking_frequency");
-
bool backup_allowed = p_preset->get("user_data_backup/allow");
int app_category = p_preset->get("package/app_category");
bool retain_data_on_uninstall = p_preset->get("package/retain_data_on_uninstall");
@@ -1027,6 +1023,10 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
encode_uint32(is_resizeable, &p_manifest.write[iofs + 16]);
}
+ if (tname == "provider" && attrname == "authorities") {
+ string_table.write[attr_value] = get_package_name(package_name) + String(".fileprovider");
+ }
+
if (tname == "supports-screens") {
if (attrname == "smallScreens") {
encode_uint32(screen_support_small ? 0xFFFFFFFF : 0, &p_manifest.write[iofs + 16]);
@@ -1042,25 +1042,6 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
}
}
- // Hand tracking related configurations
- if (xr_mode_index == XR_MODE_OPENXR && hand_tracking_index > XR_HAND_TRACKING_NONE) {
- if (tname == "meta-data" && attrname == "name" && value == "xr_hand_tracking_metadata_name") {
- string_table.write[attr_value] = "com.oculus.handtracking.frequency";
- }
-
- if (tname == "meta-data" && attrname == "value" && value == "xr_hand_tracking_metadata_value") {
- string_table.write[attr_value] = (hand_tracking_frequency_index == XR_HAND_TRACKING_FREQUENCY_LOW ? "LOW" : "HIGH");
- }
-
- if (tname == "meta-data" && attrname == "name" && value == "xr_hand_tracking_version_name") {
- string_table.write[attr_value] = "com.oculus.handtracking.version";
- }
-
- if (tname == "meta-data" && attrname == "value" && value == "xr_hand_tracking_version_value") {
- string_table.write[attr_value] = "V2.0";
- }
- }
-
iofs += 20;
}
@@ -1075,23 +1056,6 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
Vector<bool> feature_required_list;
Vector<int> feature_versions;
- if (xr_mode_index == XR_MODE_OPENXR) {
- // Check for hand tracking
- if (hand_tracking_index > XR_HAND_TRACKING_NONE) {
- feature_names.push_back("oculus.software.handtracking");
- feature_required_list.push_back(hand_tracking_index == XR_HAND_TRACKING_REQUIRED);
- feature_versions.push_back(-1); // no version attribute should be added.
- }
-
- // Check for passthrough
- int passthrough_mode = p_preset->get("xr_features/passthrough");
- if (passthrough_mode > XR_PASSTHROUGH_NONE) {
- feature_names.push_back("com.oculus.feature.PASSTHROUGH");
- feature_required_list.push_back(passthrough_mode == XR_PASSTHROUGH_REQUIRED);
- feature_versions.push_back(-1);
- }
- }
-
if (feature_names.size() > 0) {
ofs += 24; // skip over end tag
@@ -2330,6 +2294,12 @@ bool EditorExportPlatformAndroid::has_valid_project_configuration(const Ref<Edit
int xr_mode_index = p_preset->get("xr_features/xr_mode");
int hand_tracking = p_preset->get("xr_features/hand_tracking");
int passthrough_mode = p_preset->get("xr_features/passthrough");
+ if (xr_mode_index == XR_MODE_OPENXR && !custom_build_enabled) {
+ valid = false;
+ err += TTR("OpenXR requires \"Use Custom Build\" to be enabled");
+ err += "\n";
+ }
+
if (xr_mode_index != XR_MODE_OPENXR) {
if (hand_tracking > XR_HAND_TRACKING_NONE) {
valid = false;
diff --git a/platform/android/export/gradle_export_util.cpp b/platform/android/export/gradle_export_util.cpp
index 4fdcca68e9..5e71116c10 100644
--- a/platform/android/export/gradle_export_util.cpp
+++ b/platform/android/export/gradle_export_util.cpp
@@ -276,17 +276,39 @@ String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset) {
return manifest_xr_features;
}
-String _get_activity_tag(const Ref<EditorExportPreset> &p_preset) {
+String _get_activity_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_xr) {
String orientation = _get_android_orientation_label(DisplayServer::ScreenOrientation(int(GLOBAL_GET("display/window/handheld/orientation"))));
String manifest_activity_text = vformat(
" <activity android:name=\"com.godot.game.GodotApp\" "
"tools:replace=\"android:screenOrientation,android:excludeFromRecents,android:resizeableActivity\" "
+ "tools:node=\"mergeOnlyAttributes\" "
"android:excludeFromRecents=\"%s\" "
"android:screenOrientation=\"%s\" "
"android:resizeableActivity=\"%s\">\n",
bool_to_string(p_preset->get("package/exclude_from_recents")),
orientation,
bool_to_string(bool(GLOBAL_GET("display/window/size/resizable"))));
+
+ if (p_uses_xr) {
+ manifest_activity_text += " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\" />\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\" />\n"
+ "\n"
+ " <!-- Enable access to OpenXR on Oculus mobile devices, no-op on other Android\n"
+ " platforms. -->\n"
+ " <category android:name=\"com.oculus.intent.category.VR\" />\n"
+ "\n"
+ " <!-- OpenXR category tag to indicate the activity starts in an immersive OpenXR mode. \n"
+ " See https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#android-runtime-category. -->\n"
+ " <category android:name=\"org.khronos.openxr.intent.category.IMMERSIVE_HMD\" />\n"
+ " </intent-filter>\n";
+ } else {
+ manifest_activity_text += " <intent-filter>\n"
+ " <action android:name=\"android.intent.action.MAIN\" />\n"
+ " <category android:name=\"android.intent.category.LAUNCHER\" />\n"
+ " </intent-filter>\n";
+ }
+
manifest_activity_text += " </activity>\n";
return manifest_activity_text;
}
@@ -307,9 +329,7 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_
" android:hasFragileUserData=\"%s\"\n"
" android:requestLegacyExternalStorage=\"%s\"\n"
" tools:replace=\"android:allowBackup,android:appCategory,android:isGame,android:hasFragileUserData,android:requestLegacyExternalStorage\"\n"
- " tools:ignore=\"GoogleAppIndexingWarning\">\n\n"
- " <meta-data tools:node=\"remove\" android:name=\"xr_hand_tracking_version_name\" />\n"
- " <meta-data tools:node=\"remove\" android:name=\"xr_hand_tracking_metadata_name\" />\n",
+ " tools:ignore=\"GoogleAppIndexingWarning\">\n\n",
bool_to_string(p_preset->get("user_data_backup/allow")),
_get_app_category_label(app_category_index),
bool_to_string(is_game),
@@ -327,7 +347,7 @@ String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_
manifest_application_text += " <meta-data tools:node=\"replace\" android:name=\"com.oculus.handtracking.version\" android:value=\"V2.0\" />\n";
}
}
- manifest_application_text += _get_activity_tag(p_preset);
+ manifest_application_text += _get_activity_tag(p_preset, uses_xr);
manifest_application_text += " </application>\n";
return manifest_application_text;
}
diff --git a/platform/android/export/gradle_export_util.h b/platform/android/export/gradle_export_util.h
index 0fa857cb75..fe5888e11c 100644
--- a/platform/android/export/gradle_export_util.h
+++ b/platform/android/export/gradle_export_util.h
@@ -118,7 +118,7 @@ String _get_screen_sizes_tag(const Ref<EditorExportPreset> &p_preset);
String _get_xr_features_tag(const Ref<EditorExportPreset> &p_preset);
-String _get_activity_tag(const Ref<EditorExportPreset> &p_preset);
+String _get_activity_tag(const Ref<EditorExportPreset> &p_preset, bool p_uses_xr);
String _get_application_tag(const Ref<EditorExportPreset> &p_preset, bool p_has_read_write_storage_permission);
diff --git a/platform/android/java/app/AndroidManifest.xml b/platform/android/java/app/AndroidManifest.xml
index 1969f9c814..ce4a2ecfe4 100644
--- a/platform/android/java/app/AndroidManifest.xml
+++ b/platform/android/java/app/AndroidManifest.xml
@@ -31,23 +31,6 @@
android:name="org.godotengine.editor.version"
android:value="${godotEditorVersion}" />
- <!-- The following metadata values are replaced when Godot exports, modifying them here has no effect. -->
- <!-- Do these changes in the export preset. Adding new ones is fine. -->
-
- <!-- XR hand tracking metadata -->
- <!-- This is modified by the exporter based on the selected xr mode. DO NOT CHANGE the values here. -->
- <!-- Removed at export time if the xr mode is not VR or hand tracking is disabled. -->
- <meta-data
- android:name="xr_hand_tracking_metadata_name"
- android:value="xr_hand_tracking_metadata_value"/>
-
- <!-- XR hand tracking version -->
- <!-- This is modified by the exporter based on the selected xr mode. DO NOT CHANGE the values here. -->
- <!-- Removed at export time if the xr mode is not VR or hand tracking is disabled. -->
- <meta-data
- android:name="xr_hand_tracking_version_name"
- android:value="xr_hand_tracking_version_value"/>
-
<activity
android:name=".GodotApp"
android:label="@string/godot_project_name_string"
@@ -63,10 +46,6 @@
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
-
- <!-- Enable access to OpenXR on Oculus mobile devices, no-op on other Android
- platforms. -->
- <category android:name="com.oculus.intent.category.VR" />
</intent-filter>
</activity>
diff --git a/platform/android/java/lib/AndroidManifest.xml b/platform/android/java/lib/AndroidManifest.xml
index 1f77e2fc34..f03a1dd47a 100644
--- a/platform/android/java/lib/AndroidManifest.xml
+++ b/platform/android/java/lib/AndroidManifest.xml
@@ -20,6 +20,16 @@
android:exported="false"
/>
+ <provider
+ android:name="androidx.core.content.FileProvider"
+ android:authorities="${applicationId}.fileprovider"
+ android:exported="false"
+ android:grantUriPermissions="true">
+ <meta-data
+ android:name="android.support.FILE_PROVIDER_PATHS"
+ android:resource="@xml/godot_provider_paths" />
+ </provider>
+
</application>
</manifest>
diff --git a/platform/android/java/lib/res/xml/godot_provider_paths.xml b/platform/android/java/lib/res/xml/godot_provider_paths.xml
new file mode 100644
index 0000000000..1255f576bf
--- /dev/null
+++ b/platform/android/java/lib/res/xml/godot_provider_paths.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<paths xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <external-path
+ name="public"
+ path="." />
+
+ <external-files-path
+ name="app"
+ path="." />
+</paths>
diff --git a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
index 65032d6a68..677c9d8f13 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/FullScreenGodotApp.java
@@ -99,7 +99,7 @@ public abstract class FullScreenGodotApp extends FragmentActivity implements God
// from scratch. Therefore, we need to kill the whole app process and relaunch it.
//
// Restarting only the activity, wouldn't be enough unless it did proper cleanup (including
- // releasing and reloading native libs or resetting their state somehow and clearing statics).
+ // releasing and reloading native libs or resetting their state somehow and clearing static data).
Log.v(TAG, "Restarting Godot instance...");
ProcessPhoenix.triggerRebirth(FullScreenGodotApp.this);
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index 41d06a6458..edcd9c4d1f 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -49,6 +49,9 @@ import android.view.Display;
import android.view.DisplayCutout;
import android.view.WindowInsets;
+import androidx.core.content.FileProvider;
+
+import java.io.File;
import java.util.List;
import java.util.Locale;
@@ -84,29 +87,42 @@ public class GodotIO {
// MISCELLANEOUS OS IO
/////////////////////////
- public int openURI(String p_uri) {
+ public int openURI(String uriString) {
try {
- String path = p_uri;
- String type = "";
- if (path.startsWith("/")) {
- //absolute path to filesystem, prepend file://
- path = "file://" + path;
- if (p_uri.endsWith(".png") || p_uri.endsWith(".jpg") || p_uri.endsWith(".gif") || p_uri.endsWith(".webp")) {
- type = "image/*";
+ Uri dataUri;
+ String dataType = "";
+ boolean grantReadUriPermission = false;
+
+ if (uriString.startsWith("/") || uriString.startsWith("file://")) {
+ String filePath = uriString;
+ // File uris needs to be provided via the FileProvider
+ grantReadUriPermission = true;
+ if (filePath.startsWith("file://")) {
+ filePath = filePath.replace("file://", "");
}
+
+ File targetFile = new File(filePath);
+ dataUri = FileProvider.getUriForFile(activity, activity.getPackageName() + ".fileprovider", targetFile);
+ dataType = activity.getContentResolver().getType(dataUri);
+ } else {
+ dataUri = Uri.parse(uriString);
}
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
- if (!type.equals("")) {
- intent.setDataAndType(Uri.parse(path), type);
+ if (TextUtils.isEmpty(dataType)) {
+ intent.setData(dataUri);
} else {
- intent.setData(Uri.parse(path));
+ intent.setDataAndType(dataUri, dataType);
+ }
+ if (grantReadUriPermission) {
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
activity.startActivity(intent);
return 0;
} catch (ActivityNotFoundException e) {
+ Log.e(TAG, "Unable to open uri " + uriString, e);
return 1;
}
}
diff --git a/platform/linuxbsd/os_linuxbsd.cpp b/platform/linuxbsd/os_linuxbsd.cpp
index 75c23655f2..41d1f1d050 100644
--- a/platform/linuxbsd/os_linuxbsd.cpp
+++ b/platform/linuxbsd/os_linuxbsd.cpp
@@ -81,7 +81,7 @@ void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
List<String> args;
if (program.ends_with("zenity")) {
- args.push_back("--error");
+ args.push_back("--warning");
args.push_back("--width");
args.push_back("500");
args.push_back("--title");
@@ -91,7 +91,9 @@ void OS_LinuxBSD::alert(const String &p_alert, const String &p_title) {
}
if (program.ends_with("kdialog")) {
- args.push_back("--error");
+ // `--sorry` uses the same icon as `--warning` in Zenity.
+ // As of KDialog 22.12.1, its `--warning` options are only available for yes/no questions.
+ args.push_back("--sorry");
args.push_back(p_alert);
args.push_back("--title");
args.push_back(p_title);
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index c09da2f7b3..8377e81a53 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -3672,8 +3672,23 @@ Rect2i DisplayServerX11::window_get_popup_safe_rect(WindowID p_window) const {
void DisplayServerX11::popup_open(WindowID p_window) {
_THREAD_SAFE_METHOD_
+ bool has_popup_ancestor = false;
+ WindowID transient_root = p_window;
+ while (true) {
+ WindowID parent = windows[transient_root].transient_parent;
+ if (parent == INVALID_WINDOW_ID) {
+ break;
+ } else {
+ transient_root = parent;
+ if (windows[parent].is_popup) {
+ has_popup_ancestor = true;
+ break;
+ }
+ }
+ }
+
WindowData &wd = windows[p_window];
- if (wd.is_popup) {
+ if (wd.is_popup || has_popup_ancestor) {
// Find current popup parent, or root popup if new window is not transient.
List<WindowID>::Element *C = nullptr;
List<WindowID>::Element *E = popup_list.back();
@@ -4897,7 +4912,7 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
// handling decorations and placement.
// On the other hand, focus changes need to be handled manually when this is set.
// - save_under is a hint for the WM to keep the content of windows behind to avoid repaint.
- if (wd.is_popup || wd.no_focus) {
+ if (wd.no_focus) {
windowAttributes.override_redirect = True;
windowAttributes.save_under = True;
valuemask |= CWOverrideRedirect | CWSaveUnder;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 2832495693..65546392c1 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -3681,8 +3681,23 @@ Rect2i DisplayServerMacOS::window_get_popup_safe_rect(WindowID p_window) const {
void DisplayServerMacOS::popup_open(WindowID p_window) {
_THREAD_SAFE_METHOD_
+ bool has_popup_ancestor = false;
+ WindowID transient_root = p_window;
+ while (true) {
+ WindowID parent = windows[transient_root].transient_parent;
+ if (parent == INVALID_WINDOW_ID) {
+ break;
+ } else {
+ transient_root = parent;
+ if (windows[parent].is_popup) {
+ has_popup_ancestor = true;
+ break;
+ }
+ }
+ }
+
WindowData &wd = windows[p_window];
- if (wd.is_popup) {
+ if (wd.is_popup || has_popup_ancestor) {
bool was_empty = popup_list.is_empty();
// Find current popup parent, or root popup if new window is not transient.
List<WindowID>::Element *C = nullptr;
@@ -3905,6 +3920,7 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
}
}
show_window(MAIN_WINDOW_ID);
+ force_process_and_drop_events();
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index ebd0733c55..fe7d91dc18 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -829,6 +829,10 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
}
DestroyWindow(windows[p_window].hWnd);
windows.erase(p_window);
+
+ if (last_focused_window == p_window) {
+ last_focused_window = INVALID_WINDOW_ID;
+ }
}
void DisplayServerWindows::gl_window_make_current(DisplayServer::WindowID p_window_id) {
@@ -991,15 +995,6 @@ void DisplayServerWindows::window_set_current_screen(int p_screen, WindowID p_wi
wpos.y = CLAMP(wpos.y, srect.position.y, srect.position.y + srect.size.height - wsize.height / 3);
window_set_position(wpos, 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 {
@@ -1077,15 +1072,6 @@ void DisplayServerWindows::window_set_position(const Point2i &p_position, Window
AdjustWindowRectEx(&rc, style, false, exStyle);
MoveWindow(wd.hWnd, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
- // Don't let the mouse leave the window when moved.
- if (mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
- RECT rect;
- GetClientRect(wd.hWnd, &rect);
- ClientToScreen(wd.hWnd, (POINT *)&rect.left);
- ClientToScreen(wd.hWnd, (POINT *)&rect.right);
- ClipCursor(&rect);
- }
-
wd.last_pos = p_position;
_update_real_mouse_position(p_window);
}
@@ -1227,15 +1213,6 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo
}
MoveWindow(wd.hWnd, rect.left, rect.top, w, h, TRUE);
-
- // 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);
- }
}
Size2i DisplayServerWindows::window_get_size(WindowID p_window) const {
@@ -1423,15 +1400,6 @@ 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 {
@@ -2396,8 +2364,23 @@ Rect2i DisplayServerWindows::window_get_popup_safe_rect(WindowID p_window) const
void DisplayServerWindows::popup_open(WindowID p_window) {
_THREAD_SAFE_METHOD_
- const WindowData &wd = windows[p_window];
- if (wd.is_popup) {
+ bool has_popup_ancestor = false;
+ WindowID transient_root = p_window;
+ while (true) {
+ WindowID parent = windows[transient_root].transient_parent;
+ if (parent == INVALID_WINDOW_ID) {
+ break;
+ } else {
+ transient_root = parent;
+ if (windows[parent].is_popup) {
+ has_popup_ancestor = true;
+ break;
+ }
+ }
+ }
+
+ WindowData &wd = windows[p_window];
+ if (wd.is_popup || has_popup_ancestor) {
// Find current popup parent, or root popup if new window is not transient.
List<WindowID>::Element *C = nullptr;
List<WindowID>::Element *E = popup_list.back();
@@ -3381,6 +3364,15 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
Callable::CallError ce;
window.rect_changed_callback.callp(args, 1, ret, ce);
}
+
+ // Update cursor clip region after window rect has changed.
+ if (mouse_mode == MOUSE_MODE_CAPTURED || mouse_mode == MOUSE_MODE_CONFINED || mouse_mode == MOUSE_MODE_CONFINED_HIDDEN) {
+ RECT crect;
+ GetClientRect(window.hWnd, &crect);
+ ClientToScreen(window.hWnd, (POINT *)&crect.left);
+ ClientToScreen(window.hWnd, (POINT *)&crect.right);
+ ClipCursor(&crect);
+ }
}
// Return here to prevent WM_MOVE and WM_SIZE from being sent
@@ -3971,10 +3963,19 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
wd.im_position = Vector2();
- // FIXME this is wrong in cases where the window coordinates were changed due to full screen mode; use WindowRect
- wd.last_pos = p_rect.position;
- wd.width = p_rect.size.width;
- wd.height = p_rect.size.height;
+ if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN || p_mode == WINDOW_MODE_MAXIMIZED) {
+ RECT r;
+ GetClientRect(wd.hWnd, &r);
+ ClientToScreen(wd.hWnd, (POINT *)&r.left);
+ ClientToScreen(wd.hWnd, (POINT *)&r.right);
+ wd.last_pos = Point2i(r.left, r.top) - _get_screens_origin();
+ wd.width = r.right - r.left;
+ wd.height = r.bottom - r.top;
+ } else {
+ wd.last_pos = p_rect.position;
+ wd.width = p_rect.size.width;
+ wd.height = p_rect.size.height;
+ }
window_id_counter++;
}