From 28db3c715862cd25e92a4063d95ef115255cf604 Mon Sep 17 00:00:00 2001
From: bruvzg <7645683+bruvzg@users.noreply.github.com>
Date: Thu, 15 Jun 2023 10:53:31 +0300
Subject: [PATCH] =?UTF-8?q?=EF=BB=BF[DisplayServer]=20Add=20method=20to=20?=
=?UTF-8?q?check=20if=20native=20window=20is=20focused.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
doc/classes/DisplayServer.xml | 7 +++++++
platform/android/display_server_android.cpp | 4 ++++
platform/android/display_server_android.h | 1 +
platform/ios/display_server_ios.h | 1 +
platform/ios/display_server_ios.mm | 4 ++++
platform/linuxbsd/x11/display_server_x11.cpp | 9 +++++++++
platform/linuxbsd/x11/display_server_x11.h | 1 +
platform/macos/display_server_macos.h | 2 ++
platform/macos/display_server_macos.mm | 9 +++++++++
platform/macos/godot_window_delegate.mm | 11 ++++++++---
platform/web/display_server_web.cpp | 4 ++++
platform/web/display_server_web.h | 1 +
platform/windows/display_server_windows.cpp | 9 +++++++++
platform/windows/display_server_windows.h | 1 +
scene/main/window.cpp | 8 +++++++-
servers/display_server.cpp | 1 +
servers/display_server.h | 1 +
servers/display_server_headless.h | 1 +
18 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml
index cd39543c453..194fc8a5030 100644
--- a/doc/classes/DisplayServer.xml
+++ b/doc/classes/DisplayServer.xml
@@ -1258,6 +1258,13 @@
Returns the V-Sync mode of the given window.
+
+
+
+
+ Returns [code]true[/code] if the window specified by [param window_id] is focused.
+
+
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index 4d9a49c35cd..f02b292868d 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -453,6 +453,10 @@ void DisplayServerAndroid::window_move_to_foreground(DisplayServer::WindowID p_w
// Not supported on Android.
}
+bool DisplayServerAndroid::window_is_focused(WindowID p_window) const {
+ return true;
+}
+
bool DisplayServerAndroid::window_can_draw(DisplayServer::WindowID p_window) const {
return true;
}
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index ad1cbddb08b..e0ad2cb9161 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -178,6 +178,7 @@ public:
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/ios/display_server_ios.h b/platform/ios/display_server_ios.h
index b29bdeec621..da16449c613 100644
--- a/platform/ios/display_server_ios.h
+++ b/platform/ios/display_server_ios.h
@@ -193,6 +193,7 @@ public:
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual float screen_get_max_scale() const override;
diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm
index bfb09b68615..7d91274a0c5 100644
--- a/platform/ios/display_server_ios.mm
+++ b/platform/ios/display_server_ios.mm
@@ -562,6 +562,10 @@ void DisplayServerIOS::window_move_to_foreground(WindowID p_window) {
// Probably not supported for iOS
}
+bool DisplayServerIOS::window_is_focused(WindowID p_window) const {
+ return true;
+}
+
float DisplayServerIOS::screen_get_max_scale() const {
return screen_get_scale(SCREEN_OF_MAIN_WINDOW);
}
diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp
index 83b6fb76284..a607e26ac54 100644
--- a/platform/linuxbsd/x11/display_server_x11.cpp
+++ b/platform/linuxbsd/x11/display_server_x11.cpp
@@ -2626,6 +2626,15 @@ void DisplayServerX11::window_move_to_foreground(WindowID p_window) {
XFlush(x11_display);
}
+bool DisplayServerX11::window_is_focused(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND_V(!windows.has(p_window), false);
+ const WindowData &wd = windows[p_window];
+
+ return wd.focused;
+}
+
bool DisplayServerX11::window_can_draw(WindowID p_window) const {
//this seems to be all that is provided by X11
return window_get_mode(p_window) != WINDOW_MODE_MINIMIZED;
diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h
index 176a1ffb9ab..180362923ba 100644
--- a/platform/linuxbsd/x11/display_server_x11.h
+++ b/platform/linuxbsd/x11/display_server_x11.h
@@ -477,6 +477,7 @@ public:
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h
index 5944cc8abd8..93fa93b2592 100644
--- a/platform/macos/display_server_macos.h
+++ b/platform/macos/display_server_macos.h
@@ -117,6 +117,7 @@ public:
bool no_focus = false;
bool is_popup = false;
bool mpass = false;
+ bool focused = false;
Rect2i parent_safe_rect;
};
@@ -390,6 +391,7 @@ public:
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm
index b77715d6486..a0a851b7dce 100644
--- a/platform/macos/display_server_macos.mm
+++ b/platform/macos/display_server_macos.mm
@@ -3075,6 +3075,15 @@ void DisplayServerMacOS::window_move_to_foreground(WindowID p_window) {
}
}
+bool DisplayServerMacOS::window_is_focused(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND_V(!windows.has(p_window), false);
+ const WindowData &wd = windows[p_window];
+
+ return wd.focused;
+}
+
bool DisplayServerMacOS::window_can_draw(WindowID p_window) const {
return window_get_mode(p_window) != WINDOW_MODE_MINIMIZED;
}
diff --git a/platform/macos/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm
index df971c51392..1c6dbb1981a 100644
--- a/platform/macos/godot_window_delegate.mm
+++ b/platform/macos/godot_window_delegate.mm
@@ -314,6 +314,7 @@
[self windowDidResize:notification]; // Emit resize event, to ensure content is resized if the window was resized while it was hidden.
+ wd.focused = true;
ds->set_last_focused_window(window_id);
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN);
}
@@ -330,6 +331,7 @@
[(GodotButtonView *)wd.window_button_view displayButtons];
}
+ wd.focused = false;
ds->release_pressed_events();
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT);
}
@@ -342,6 +344,7 @@
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
+ wd.focused = false;
ds->release_pressed_events();
ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT);
}
@@ -353,9 +356,11 @@
}
DisplayServerMacOS::WindowData &wd = ds->get_window(window_id);
-
- ds->set_last_focused_window(window_id);
- ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN);
+ if ([wd.window_object isKeyWindow]) {
+ wd.focused = true;
+ ds->set_last_focused_window(window_id);
+ ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN);
+ }
}
@end
diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp
index 6cb56b404fd..951ce110e02 100644
--- a/platform/web/display_server_web.cpp
+++ b/platform/web/display_server_web.cpp
@@ -1073,6 +1073,10 @@ void DisplayServerWeb::window_move_to_foreground(WindowID p_window) {
// Not supported.
}
+bool DisplayServerWeb::window_is_focused(WindowID p_window) const {
+ return true;
+}
+
bool DisplayServerWeb::window_can_draw(WindowID p_window) const {
return true;
}
diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h
index 3b03b102cdb..a4fd75f33b3 100644
--- a/platform/web/display_server_web.h
+++ b/platform/web/display_server_web.h
@@ -211,6 +211,7 @@ public:
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp
index fc208eb4bb0..ea93c47ec5e 100644
--- a/platform/windows/display_server_windows.cpp
+++ b/platform/windows/display_server_windows.cpp
@@ -1615,6 +1615,15 @@ void DisplayServerWindows::window_move_to_foreground(WindowID p_window) {
}
}
+bool DisplayServerWindows::window_is_focused(WindowID p_window) const {
+ _THREAD_SAFE_METHOD_
+
+ ERR_FAIL_COND_V(!windows.has(p_window), false);
+ const WindowData &wd = windows[p_window];
+
+ return wd.window_focused;
+}
+
bool DisplayServerWindows::window_can_draw(WindowID p_window) const {
_THREAD_SAFE_METHOD_
diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h
index ae2cd4e8b59..7228de7d317 100644
--- a/platform/windows/display_server_windows.h
+++ b/platform/windows/display_server_windows.h
@@ -594,6 +594,7 @@ public:
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override;
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override;
+ virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override;
virtual bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index b82b215e546..e8395f59c96 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -616,6 +616,8 @@ void Window::_update_from_window() {
void Window::_clear_window() {
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
+ bool had_focus = has_focus();
+
DisplayServer::get_singleton()->window_set_rect_changed_callback(Callable(), window_id);
DisplayServer::get_singleton()->window_set_window_event_callback(Callable(), window_id);
DisplayServer::get_singleton()->window_set_input_event_callback(Callable(), window_id);
@@ -638,7 +640,7 @@ void Window::_clear_window() {
window_id = DisplayServer::INVALID_WINDOW_ID;
// If closing window was focused and has a parent, return focus.
- if (focused && transient_parent) {
+ if (had_focus && transient_parent) {
transient_parent->grab_focus();
}
@@ -1185,6 +1187,7 @@ void Window::_notification(int p_what) {
{
position = DisplayServer::get_singleton()->window_get_position(window_id);
size = DisplayServer::get_singleton()->window_get_size(window_id);
+ focused = DisplayServer::get_singleton()->window_is_focused(window_id);
}
_update_window_size(); // Inform DisplayServer of minimum and maximum size.
_update_viewport_size(); // Then feed back to the viewport.
@@ -1762,6 +1765,9 @@ void Window::grab_focus() {
bool Window::has_focus() const {
ERR_READ_THREAD_GUARD_V(false);
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ return DisplayServer::get_singleton()->window_is_focused(window_id);
+ }
return focused;
}
diff --git a/servers/display_server.cpp b/servers/display_server.cpp
index 516f2f1be6b..41fa0d2d477 100644
--- a/servers/display_server.cpp
+++ b/servers/display_server.cpp
@@ -716,6 +716,7 @@ void DisplayServer::_bind_methods() {
ClassDB::bind_method(D_METHOD("window_request_attention", "window_id"), &DisplayServer::window_request_attention, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_move_to_foreground", "window_id"), &DisplayServer::window_move_to_foreground, DEFVAL(MAIN_WINDOW_ID));
+ ClassDB::bind_method(D_METHOD("window_is_focused", "window_id"), &DisplayServer::window_is_focused, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_can_draw", "window_id"), &DisplayServer::window_can_draw, DEFVAL(MAIN_WINDOW_ID));
ClassDB::bind_method(D_METHOD("window_set_transient", "window_id", "parent_window_id"), &DisplayServer::window_set_transient);
diff --git a/servers/display_server.h b/servers/display_server.h
index d8e67b4f927..fc8207f2d36 100644
--- a/servers/display_server.h
+++ b/servers/display_server.h
@@ -424,6 +424,7 @@ public:
virtual void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) = 0;
+ virtual bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const = 0;
virtual void window_set_window_buttons_offset(const Vector2i &p_offset, WindowID p_window = MAIN_WINDOW_ID) {}
virtual Vector3i window_get_safe_title_margins(WindowID p_window = MAIN_WINDOW_ID) const { return Vector3i(); }
diff --git a/servers/display_server_headless.h b/servers/display_server_headless.h
index 0c43b84f2ee..af13f8db21c 100644
--- a/servers/display_server_headless.h
+++ b/servers/display_server_headless.h
@@ -119,6 +119,7 @@ public:
void window_request_attention(WindowID p_window = MAIN_WINDOW_ID) override {}
void window_move_to_foreground(WindowID p_window = MAIN_WINDOW_ID) override {}
+ bool window_is_focused(WindowID p_window = MAIN_WINDOW_ID) const override { return true; };
bool window_can_draw(WindowID p_window = MAIN_WINDOW_ID) const override { return false; }