Merge pull request #77842 from Sauermann/fix-unfocusable-subwindow

Fix input handling for unfocusable embedded windows
This commit is contained in:
Rémi Verschelde 2023-06-08 17:38:33 +02:00 committed by GitHub
commit 3a19d81691
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 21 deletions

View file

@ -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<InputEvent> &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<InputEventMouseButton> 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<InputEvent> &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<InputEvent> &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<InputEvent> &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<InputEvent> &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<InputEvent> &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<InputEvent> &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<InputEvent> &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<InputEvent> &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<InputEvent> &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);

View file

@ -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;