summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbruvzg <7645683+bruvzg@users.noreply.github.com>2022-11-19 22:25:43 +0200
committerbruvzg <7645683+bruvzg@users.noreply.github.com>2022-11-21 10:11:14 +0200
commitc2b061dec310f47e73e062d9891cd9e7d56c3bfa (patch)
tree3caf7dc2398e6e1e560365a1b190c11597db6515
parentdce1602edacd8ad96a70f29e4f524d7b7c231e3f (diff)
[macOS] Dynamically attach and detach transient windows to allow them to stay on top of parent and can be moved to another screen.
-rw-r--r--platform/macos/display_server_macos.h1
-rw-r--r--platform/macos/display_server_macos.mm71
-rw-r--r--platform/macos/godot_window_delegate.mm9
3 files changed, 64 insertions, 17 deletions
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 8e75b98302..8f315f736b 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -233,6 +233,7 @@ public:
void popup_close(WindowID p_window);
void set_is_resizing(bool p_is_resizing);
bool get_is_resizing() const;
+ void reparent_check(WindowID p_window);
void window_update(WindowID p_window);
void window_destroy(WindowID p_window);
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index 3557511c28..3aff5b8b7e 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -2337,22 +2337,64 @@ void DisplayServerMacOS::window_set_current_screen(int p_screen, WindowID p_wind
}
}
-void DisplayServerMacOS::window_set_exclusive(WindowID p_window, bool p_exclusive) {
- _THREAD_SAFE_METHOD_
+void DisplayServerMacOS::reparent_check(WindowID p_window) {
ERR_FAIL_COND(!windows.has(p_window));
WindowData &wd = windows[p_window];
- if (wd.exclusive != p_exclusive) {
- wd.exclusive = p_exclusive;
- if (wd.transient_parent != INVALID_WINDOW_ID) {
- WindowData &wd_parent = windows[wd.transient_parent];
- if (wd.exclusive) {
- ERR_FAIL_COND_MSG([[wd_parent.window_object childWindows] count] > 0, "Transient parent has another exclusive child.");
+ NSScreen *screen = [wd.window_object screen];
+
+ if (wd.transient_parent != INVALID_WINDOW_ID) {
+ WindowData &wd_parent = windows[wd.transient_parent];
+ NSScreen *parent_screen = [wd_parent.window_object screen];
+
+ if (parent_screen == screen) {
+ if (![[wd_parent.window_object childWindows] containsObject:wd.window_object]) {
+ if (wd.exclusive) {
+ ERR_FAIL_COND_MSG([[wd_parent.window_object childWindows] count] > 0, "Transient parent has another exclusive child.");
+ }
+ [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
[wd_parent.window_object addChildWindow:wd.window_object ordered:NSWindowAbove];
- } else {
+ }
+ } else {
+ if ([[wd_parent.window_object childWindows] containsObject:wd.window_object]) {
[wd_parent.window_object removeChildWindow:wd.window_object];
+ [wd.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+ [wd.window_object orderFront:nil];
}
}
}
+
+ for (const WindowID &child : wd.transient_children) {
+ WindowData &wd_child = windows[child];
+ NSScreen *child_screen = [wd_child.window_object screen];
+
+ if (child_screen == screen) {
+ if (![[wd.window_object childWindows] containsObject:wd_child.window_object]) {
+ if (wd_child.exclusive) {
+ ERR_FAIL_COND_MSG([[wd.window_object childWindows] count] > 0, "Transient parent has another exclusive child.");
+ }
+ if (wd_child.fullscreen) {
+ [wd_child.window_object toggleFullScreen:nil];
+ }
+ [wd_child.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
+ [wd.window_object addChildWindow:wd_child.window_object ordered:NSWindowAbove];
+ }
+ } else {
+ if ([[wd.window_object childWindows] containsObject:wd_child.window_object]) {
+ [wd.window_object removeChildWindow:wd_child.window_object];
+ [wd_child.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
+ }
+ }
+ }
+}
+
+void DisplayServerMacOS::window_set_exclusive(WindowID p_window, bool p_exclusive) {
+ _THREAD_SAFE_METHOD_
+ ERR_FAIL_COND(!windows.has(p_window));
+ WindowData &wd = windows[p_window];
+ if (wd.exclusive != p_exclusive) {
+ wd.exclusive = p_exclusive;
+ reparent_check(p_window);
+ }
}
Point2i DisplayServerMacOS::window_get_position(WindowID p_window) const {
@@ -2429,11 +2471,10 @@ void DisplayServerMacOS::window_set_transient(WindowID p_window, WindowID p_pare
wd_window.transient_parent = INVALID_WINDOW_ID;
wd_parent.transient_children.erase(p_window);
- [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
-
- if (wd_window.exclusive) {
+ if ([[wd_parent.window_object childWindows] containsObject:wd_window.window_object]) {
[wd_parent.window_object removeChildWindow:wd_window.window_object];
}
+ [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
} else {
ERR_FAIL_COND(!windows.has(p_parent));
ERR_FAIL_COND_MSG(wd_window.transient_parent != INVALID_WINDOW_ID, "Window already has a transient parent");
@@ -2441,11 +2482,7 @@ void DisplayServerMacOS::window_set_transient(WindowID p_window, WindowID p_pare
wd_window.transient_parent = p_parent;
wd_parent.transient_children.insert(p_window);
- [wd_window.window_object setCollectionBehavior:NSWindowCollectionBehaviorFullScreenAuxiliary];
-
- if (wd_window.exclusive) {
- [wd_parent.window_object addChildWindow:wd_window.window_object ordered:NSWindowAbove];
- }
+ reparent_check(p_window);
}
}
diff --git a/platform/macos/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm
index 3bdbc8c5ec..27efd3ebb2 100644
--- a/platform/macos/godot_window_delegate.mm
+++ b/platform/macos/godot_window_delegate.mm
@@ -256,6 +256,15 @@
}
}
+- (void)windowDidChangeScreen:(NSNotification *)notification {
+ DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
+ if (!ds || !ds->has_window(window_id)) {
+ return;
+ }
+
+ ds->reparent_check(window_id);
+}
+
- (void)windowDidMove:(NSNotification *)notification {
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
if (!ds || !ds->has_window(window_id)) {