Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Game and editor freeze when clicking on the game's title bar #102744

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions editor/plugins/game_view_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -786,8 +795,21 @@ void GameView::_update_arguments_for_instance(int p_idx, List<String> &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");
Expand Down
8 changes: 8 additions & 0 deletions editor/window_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
1 change: 1 addition & 0 deletions editor/window_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class WindowWrapper : public MarginContainer {
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);
Expand Down
9 changes: 9 additions & 0 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down