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 subviewports receiving gui input too early #55300

Closed
Closed
Show file tree
Hide file tree
Changes from 5 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
10 changes: 10 additions & 0 deletions doc/classes/Viewport.xml
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,20 @@
<description>
</description>
</method>
<method name="push_gui_input">
<return type="void" />
<argument index="0" name="event" type="InputEvent" />
<argument index="1" name="in_local_coords" type="bool" default="false" />
<description>
Pushes an input event to [method Control._gui_input]
</description>
zhehangd marked this conversation as resolved.
Show resolved Hide resolved
</method>
<method name="push_input">
<return type="void" />
<argument index="0" name="event" type="InputEvent" />
<argument index="1" name="in_local_coords" type="bool" default="false" />
<description>
Pushes an input event to [method Node._input]
</description>
</method>
<method name="push_text_input">
Expand All @@ -148,6 +157,7 @@
<argument index="0" name="event" type="InputEvent" />
<argument index="1" name="in_local_coords" type="bool" default="false" />
<description>
Pushes an input event to [method Node._unhandled_input]
</description>
</method>
<method name="set_input_as_handled">
Expand Down
2 changes: 2 additions & 0 deletions scene/2d/touch_screen_button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ void TouchScreenButton::_press(int p_finger_pressed) {
iea->set_action(action);
iea->set_pressed(true);
get_viewport()->push_input(iea, true);
get_viewport()->push_gui_input(iea, true);
}

emit_signal(SNAME("pressed"));
Expand All @@ -306,6 +307,7 @@ void TouchScreenButton::_release(bool p_exiting_tree) {
iea->set_action(action);
iea->set_pressed(false);
get_viewport()->push_input(iea, true);
get_viewport()->push_gui_input(iea, true);
}
}

Expand Down
27 changes: 27 additions & 0 deletions scene/gui/subviewport_container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,33 @@ void SubViewportContainer::input(const Ref<InputEvent> &p_event) {
}
}

void SubViewportContainer::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());

if (Engine::get_singleton()->is_editor_hint()) {
return;
}

Transform2D xform = get_global_transform();

if (stretch) {
Transform2D scale_xf;
scale_xf.scale(Vector2(shrink, shrink));
xform *= scale_xf;
}

Ref<InputEvent> ev = p_event; // already transformed

for (int i = 0; i < get_child_count(); i++) {
SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
if (!c || c->is_input_disabled()) {
continue;
}

c->push_gui_input(ev);
}
}

void SubViewportContainer::unhandled_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());

Expand Down
1 change: 1 addition & 0 deletions scene/gui/subviewport_container.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class SubViewportContainer : public Container {
bool is_stretch_enabled() const;

virtual void input(const Ref<InputEvent> &p_event) override;
virtual void gui_input(const Ref<InputEvent> &p_event) override;
virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
void set_stretch_shrink(int p_shrink);
int get_stretch_shrink() const;
Expand Down
37 changes: 34 additions & 3 deletions scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2687,14 +2687,44 @@ void Viewport::push_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
}

if (!is_input_handled()) {
get_tree()->_call_input_pause(input_group, SceneTree::CALL_INPUT_TYPE_INPUT, ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
get_tree()->_call_input_pause(input_group, SceneTree::CALL_INPUT_TYPE_INPUT, ev, this);
}

event_count++;
}

void Viewport::push_gui_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
ERR_FAIL_COND(!is_inside_tree());

if (disable_input) {
return;
}

if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this)) {
return;
}

local_input_handled = false;

Ref<InputEvent> ev;
if (!p_local_coords) {
ev = _make_input_local(p_event);
} else {
ev = p_event;
}

if (is_embedding_subwindows() && _sub_windows_forward_input(p_event)) {
set_input_as_handled();
return;
}

if (!_can_consume_input_events()) {
return;
}

if (!is_input_handled()) {
_gui_input_event(ev);
}

event_count++;
}

void Viewport::push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
Expand Down Expand Up @@ -3573,6 +3603,7 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_viewport_rid"), &Viewport::get_viewport_rid);
ClassDB::bind_method(D_METHOD("push_text_input", "text"), &Viewport::push_text_input);
ClassDB::bind_method(D_METHOD("push_input", "event", "in_local_coords"), &Viewport::push_input, DEFVAL(false));
ClassDB::bind_method(D_METHOD("push_gui_input", "event", "in_local_coords"), &Viewport::push_gui_input, DEFVAL(false));
ClassDB::bind_method(D_METHOD("push_unhandled_input", "event", "in_local_coords"), &Viewport::push_unhandled_input, DEFVAL(false));

ClassDB::bind_method(D_METHOD("get_camera_2d"), &Viewport::get_camera_2d);
Expand Down
1 change: 1 addition & 0 deletions scene/main/viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,7 @@ class Viewport : public Node {

void push_text_input(const String &p_text);
void push_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
void push_gui_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
void push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);

void set_disable_input(bool p_disable);
Expand Down
1 change: 1 addition & 0 deletions scene/main/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -921,6 +921,7 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) {
emit_signal(SceneStringNames::get_singleton()->window_input, p_ev);

push_input(p_ev);
push_gui_input(p_ev);
if (!is_input_handled()) {
push_unhandled_input(p_ev);
}
Expand Down
4 changes: 2 additions & 2 deletions tests/test_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,15 @@ int register_test_command(String p_command, TestFunc p_function);
#define SEND_GUI_MOUSE_EVENT(m_object, m_local_pos, m_input, m_mask) \
{ \
_CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, m_input, m_mask); \
m_object->get_viewport()->push_input(event); \
m_object->get_viewport()->push_gui_input(event); \
MessageQueue::get_singleton()->flush(); \
}

#define SEND_GUI_DOUBLE_CLICK(m_object, m_local_pos) \
{ \
_CREATE_GUI_MOUSE_EVENT(m_object, m_local_pos, MouseButton::LEFT, MouseButton::LEFT); \
event->set_double_click(true); \
m_object->get_viewport()->push_input(event); \
m_object->get_viewport()->push_gui_input(event); \
MessageQueue::get_singleton()->flush(); \
}

Expand Down