Merge pull request #77842 from Sauermann/fix-unfocusable-subwindow
Fix input handling for unfocusable embedded windows
This commit is contained in:
commit
3a19d81691
2 changed files with 42 additions and 21 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue