From e9fef1c8339b91b2ce4bd6fae4b92e9c1157a4b4 Mon Sep 17 00:00:00 2001 From: Hilderin <81109165+Hilderin@users.noreply.github.com> Date: Tue, 11 Feb 2025 21:41:03 -0500 Subject: [PATCH] Fix Game and editor freeze when clicking on the game's title bar --- editor/plugins/game_view_plugin.cpp | 38 ++++++++++++++++----- editor/window_wrapper.cpp | 8 +++++ editor/window_wrapper.h | 1 + platform/windows/display_server_windows.cpp | 9 +++++ 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/editor/plugins/game_view_plugin.cpp b/editor/plugins/game_view_plugin.cpp index fa274f242cc..f604e977ce5 100644 --- a/editor/plugins/game_view_plugin.cpp +++ b/editor/plugins/game_view_plugin.cpp @@ -243,20 +243,29 @@ void GameView::_show_update_window_wrapper() { Size2i size = floating_window_rect.size; int screen = floating_window_screen; - Size2 wrapped_margins_size = window_wrapper->get_margins_size(); - Point2 offset_embedded_process = embedded_process->get_global_position() - get_global_position(); - offset_embedded_process.x += embedded_process->get_margin_size(SIDE_LEFT); - offset_embedded_process.y += embedded_process->get_margin_size(SIDE_TOP); - // Obtain the size around the embedded process control. Usually, the difference between the game view's get_size // and the embedded control should work. However, when the control is hidden and has never been displayed, // the size of the embedded control is not calculated. Size2 old_min_size = embedded_process->get_custom_minimum_size(); embedded_process->set_custom_minimum_size(Size2i()); - Size2 min_size = get_minimum_size(); + + Size2 embedded_process_min_size = get_minimum_size(); + Size2 wrapped_margins_size = window_wrapper->get_margins_size(); + Size2 wrapped_min_size = window_wrapper->get_minimum_size(); + Point2 offset_embedded_process = embedded_process->get_global_position() - get_global_position(); + + // On the first startup, the global position of the embedded process control is invalid because it was + // never displayed. We will calculated it manually using the minimum size of the window. + if (offset_embedded_process == Point2()) { + offset_embedded_process.y = wrapped_min_size.y; + } + offset_embedded_process.x += embedded_process->get_margin_size(SIDE_LEFT); + offset_embedded_process.y += embedded_process->get_margin_size(SIDE_TOP); + offset_embedded_process += window_wrapper->get_margins_top_left(); + embedded_process->set_custom_minimum_size(old_min_size); - Point2 size_diff_embedded_process = Point2(0, min_size.y) + embedded_process->get_margins_size(); + Point2 size_diff_embedded_process = Point2(0, embedded_process_min_size.y) + embedded_process->get_margins_size(); if (placement.position != Point2i(INT_MAX, INT_MAX)) { position = placement.position - offset_embedded_process; @@ -786,8 +795,21 @@ void GameView::_update_arguments_for_instance(int p_idx, List &r_argumen // Be sure to have the correct window size in the embedded_process control. _update_embed_window_size(); - Rect2i rect = embedded_process->get_screen_embedded_window_rect(); + + // When using the floating window, we need to force the position and size from the + // editor/project settings, because the get_screen_embedded_window_rect of the + // embedded_process will be updated only on the next frame. + if (p_idx == 0 && window_wrapper->get_window_enabled()) { + EditorRun::WindowPlacement placement = EditorRun::get_window_placement(); + if (placement.position != Point2i(INT_MAX, INT_MAX)) { + rect.position = placement.position; + } + if (placement.size != Size2i()) { + rect.size = placement.size; + } + } + N = r_arguments.insert_after(N, "--position"); N = r_arguments.insert_after(N, itos(rect.position.x) + "," + itos(rect.position.y)); N = r_arguments.insert_after(N, "--resolution"); diff --git a/editor/window_wrapper.cpp b/editor/window_wrapper.cpp index 4d82df70db9..6d24a9fd1a0 100644 --- a/editor/window_wrapper.cpp +++ b/editor/window_wrapper.cpp @@ -338,6 +338,14 @@ Size2 WindowWrapper::get_margins_size() { return Size2(margins->get_margin_size(SIDE_LEFT) + margins->get_margin_size(SIDE_RIGHT), margins->get_margin_size(SIDE_TOP) + margins->get_margin_size(SIDE_RIGHT)); } +Size2 WindowWrapper::get_margins_top_left() { + if (!margins) { + return Size2(); + } + + return Size2(margins->get_margin_size(SIDE_LEFT), margins->get_margin_size(SIDE_TOP)); +} + void WindowWrapper::grab_window_focus() { if (get_window_enabled() && is_visible()) { window->grab_focus(); diff --git a/editor/window_wrapper.h b/editor/window_wrapper.h index 360c2858ae3..3fedf3979e2 100644 --- a/editor/window_wrapper.h +++ b/editor/window_wrapper.h @@ -86,6 +86,7 @@ public: void set_window_title(const String &p_title); void set_margins_enabled(bool p_enabled); Size2 get_margins_size(); + Size2 get_margins_top_left(); void grab_window_focus(); void set_override_close_request(bool p_enabled); diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 6f92cc0d621..ceed5a9d5e4 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -6172,6 +6172,15 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, wd.parent_hwnd = p_parent_hwnd; + // Detach the input queue from the parent window. + // This prevents the embedded window from waiting on the main window's input queue, + // causing lags input lags when resizing or moving the main window. + if (p_parent_hwnd) { + DWORD mainThreadId = GetWindowThreadProcessId(owner_hwnd, nullptr); + DWORD embeddedThreadId = GetCurrentThreadId(); + AttachThreadInput(embeddedThreadId, mainThreadId, FALSE); + } + if (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN) { wd.fullscreen = true; if (p_mode == WINDOW_MODE_FULLSCREEN) {