diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index b57ee302266..076d242e38b 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -282,7 +282,15 @@ void Viewport::_sub_window_register(Window *p_window) { sw.window = p_window; gui.sub_windows.push_back(sw); - _sub_window_grab_focus(p_window); + if (gui.subwindow_drag == SUB_WINDOW_DRAG_DISABLED) { + _sub_window_grab_focus(p_window); + } else { + int index = _sub_window_find(gui.currently_dragged_subwindow); + sw = gui.sub_windows[index]; + gui.sub_windows.remove_at(index); + gui.sub_windows.push_back(sw); + _sub_window_update_order(); + } RenderingServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, viewport); } @@ -352,6 +360,12 @@ void Viewport::_sub_window_grab_focus(Window *p_window) { ERR_FAIL_COND(index == -1); if (p_window->get_flag(Window::FLAG_NO_FOCUS)) { + // Release current focus. + if (gui.subwindow_focused) { + gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT); + gui.subwindow_focused = nullptr; + gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; + } // Can only move to foreground, but no focus granted. SubWindow sw = gui.sub_windows[index]; gui.sub_windows.remove_at(index); @@ -409,12 +423,15 @@ void Viewport::_sub_window_remove(Window *p_window) { subwindow_canvas = RID(); } + if (gui.currently_dragged_subwindow == p_window) { + gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; + gui.currently_dragged_subwindow = nullptr; + } + if (gui.subwindow_focused == p_window) { Window *new_focused_window; Window *parent_visible = p_window->get_parent_visible_window(); - gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; - gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT); if (parent_visible) { @@ -2702,19 +2719,20 @@ Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subw bool Viewport::_sub_windows_forward_input(const Ref &p_event) { if (gui.subwindow_drag != SUB_WINDOW_DRAG_DISABLED) { - ERR_FAIL_COND_V(gui.subwindow_focused == nullptr, false); + ERR_FAIL_COND_V(gui.currently_dragged_subwindow == nullptr, false); Ref mb = p_event; if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) { if (gui.subwindow_drag_close_rect.has_point(mb->get_position())) { // Close window. - gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_CLOSE_REQUEST); + gui.currently_dragged_subwindow->_event_callback(DisplayServer::WINDOW_EVENT_CLOSE_REQUEST); } } gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED; - if (gui.subwindow_focused != nullptr) { // May have been erased. - _sub_window_update(gui.subwindow_focused); + if (gui.currently_dragged_subwindow != nullptr) { // May have been erased. + _sub_window_update(gui.currently_dragged_subwindow); + gui.currently_dragged_subwindow = nullptr; } } @@ -2722,13 +2740,13 @@ bool Viewport::_sub_windows_forward_input(const Ref &p_event) { if (mm.is_valid()) { if (gui.subwindow_drag == SUB_WINDOW_DRAG_MOVE) { Vector2 diff = mm->get_position() - gui.subwindow_drag_from; - Rect2i new_rect(gui.subwindow_drag_pos + diff, gui.subwindow_focused->get_size()); + Rect2i new_rect(gui.subwindow_drag_pos + diff, gui.currently_dragged_subwindow->get_size()); - if (gui.subwindow_focused->is_clamped_to_embedder()) { - new_rect = gui.subwindow_focused->fit_rect_in_parent(new_rect, get_visible_rect()); + if (gui.currently_dragged_subwindow->is_clamped_to_embedder()) { + new_rect = gui.currently_dragged_subwindow->fit_rect_in_parent(new_rect, get_visible_rect()); } - gui.subwindow_focused->_rect_changed_callback(new_rect); + gui.currently_dragged_subwindow->_rect_changed_callback(new_rect); if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_CURSOR_SHAPE)) { DisplayServer::get_singleton()->cursor_set_shape(DisplayServer::CURSOR_MOVE); @@ -2739,8 +2757,8 @@ bool Viewport::_sub_windows_forward_input(const Ref &p_event) { } if (gui.subwindow_drag == SUB_WINDOW_DRAG_RESIZE) { Vector2i diff = mm->get_position() - gui.subwindow_drag_from; - Size2i min_size = gui.subwindow_focused->get_min_size(); - Size2i min_size_clamped = gui.subwindow_focused->get_clamped_minimum_size(); + Size2i min_size = gui.currently_dragged_subwindow->get_min_size(); + Size2i min_size_clamped = gui.currently_dragged_subwindow->get_clamped_minimum_size(); min_size_clamped.x = MAX(min_size_clamped.x, 1); min_size_clamped.y = MAX(min_size_clamped.y, 1); @@ -2802,7 +2820,7 @@ bool Viewport::_sub_windows_forward_input(const Ref &p_event) { } } - Size2i max_size = gui.subwindow_focused->get_max_size(); + Size2i max_size = gui.currently_dragged_subwindow->get_max_size(); if ((max_size.x > 0 || max_size.y > 0) && (max_size.x >= min_size.x && max_size.y >= min_size.y)) { max_size.x = MAX(max_size.x, 1); max_size.y = MAX(max_size.y, 1); @@ -2815,11 +2833,11 @@ bool Viewport::_sub_windows_forward_input(const Ref &p_event) { } } - gui.subwindow_focused->_rect_changed_callback(r); + gui.currently_dragged_subwindow->_rect_changed_callback(r); } - if (gui.subwindow_focused) { // May have been erased. - _sub_window_update(gui.subwindow_focused); + if (gui.currently_dragged_subwindow) { // May have been erased. + _sub_window_update(gui.currently_dragged_subwindow); } } @@ -2829,7 +2847,7 @@ bool Viewport::_sub_windows_forward_input(const Ref &p_event) { // If the event is a mouse button, we need to check whether another window was clicked. if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == MouseButton::LEFT) { - bool click_on_window = false; + Window *click_on_window = nullptr; for (int i = gui.sub_windows.size() - 1; i >= 0; i--) { SubWindow sw = gui.sub_windows.write[i]; @@ -2845,7 +2863,7 @@ bool Viewport::_sub_windows_forward_input(const Ref &p_event) { title_bar.size.y = title_height; if (title_bar.size.y > 0 && title_bar.has_point(mb->get_position())) { - click_on_window = true; + click_on_window = sw.window; int close_h_ofs = sw.window->get_theme_constant(SNAME("close_h_offset")); int close_v_ofs = sw.window->get_theme_constant(SNAME("close_v_offset")); @@ -2883,7 +2901,7 @@ bool Viewport::_sub_windows_forward_input(const Ref &p_event) { gui.subwindow_resize_from_rect = r; gui.subwindow_drag_from = mb->get_position(); gui.subwindow_drag = SUB_WINDOW_DRAG_RESIZE; - click_on_window = true; + click_on_window = sw.window; } } } @@ -2894,7 +2912,7 @@ bool Viewport::_sub_windows_forward_input(const Ref &p_event) { _sub_window_grab_focus(sw.window); } - click_on_window = true; + click_on_window = sw.window; } if (click_on_window) { @@ -2902,6 +2920,8 @@ bool Viewport::_sub_windows_forward_input(const Ref &p_event) { } } + gui.currently_dragged_subwindow = click_on_window; + if (!click_on_window && gui.subwindow_focused) { // No window found and clicked, remove focus. _sub_window_grab_focus(nullptr); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 1cb32d4509c..b8db29e197c 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -388,6 +388,7 @@ private: bool embed_subwindows_hint = false; Window *subwindow_focused = nullptr; + Window *currently_dragged_subwindow = nullptr; SubWindowDrag subwindow_drag = SUB_WINDOW_DRAG_DISABLED; Vector2 subwindow_drag_from; Vector2 subwindow_drag_pos;