diff --git a/doc/classes/SubViewportContainer.xml b/doc/classes/SubViewportContainer.xml
index 2f666f5089bd..08e7ca23f74a 100644
--- a/doc/classes/SubViewportContainer.xml
+++ b/doc/classes/SubViewportContainer.xml
@@ -11,6 +11,7 @@
+
If [code]true[/code], the sub-viewport will be automatically resized to the control's size.
[b]Note:[/b] If [code]true[/code], this will prohibit changing [member SubViewport.size] of its children manually.
diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml
index c0c53146fe31..9a5e7ed6f643 100644
--- a/doc/classes/Viewport.xml
+++ b/doc/classes/Viewport.xml
@@ -160,8 +160,8 @@
- [method Node._input]
- [method Control._gui_input] for [Control] nodes
- [method Node._shortcut_input]
- - [method Node._unhandled_input]
- [method Node._unhandled_key_input]
+ - [method Node._unhandled_input]
If an earlier method marks the input as handled via [method set_input_as_handled], any later method in this list will not be called.
If none of the methods handle the event and [member physics_object_picking] is [code]true[/code], the event is used for physics object picking.
@@ -183,8 +183,8 @@
While this method serves a similar purpose as [method Input.parse_input_event], it does not remap the specified [param event] based on project settings like [member ProjectSettings.input_devices/pointing/emulate_touch_from_mouse].
Calling this method will propagate calls to child nodes for following methods in the given order:
- [method Node._shortcut_input]
- - [method Node._unhandled_input]
- [method Node._unhandled_key_input]
+ - [method Node._unhandled_input]
If an earlier method marks the input as handled via [method set_input_as_handled], any later method in this list will not be called.
If none of the methods handle the event and [member physics_object_picking] is [code]true[/code], the event is used for physics object picking.
[b]Note:[/b] This method doesn't propagate input events to embedded [Window]s or [SubViewport]s.
diff --git a/scene/gui/subviewport_container.cpp b/scene/gui/subviewport_container.cpp
index 910583748692..8142fc204af9 100644
--- a/scene/gui/subviewport_container.cpp
+++ b/scene/gui/subviewport_container.cpp
@@ -154,6 +154,18 @@ void SubViewportContainer::_notification(int p_what) {
case NOTIFICATION_MOUSE_EXIT: {
_notify_viewports(NOTIFICATION_VP_MOUSE_EXIT);
} break;
+
+ case NOTIFICATION_FOCUS_ENTER: {
+ // If focused, send InputEvent to the SubViewport before the Gui-Input stage.
+ set_process_input(true);
+ set_process_unhandled_input(false);
+ } break;
+
+ case NOTIFICATION_FOCUS_EXIT: {
+ // A different Control has focus and should receive Gui-Input before the InputEvent is sent to the SubViewport.
+ set_process_input(false);
+ set_process_unhandled_input(true);
+ } break;
}
}
@@ -168,6 +180,14 @@ void SubViewportContainer::_notify_viewports(int p_notification) {
}
void SubViewportContainer::input(const Ref &p_event) {
+ _propagate_nonpositional_event(p_event);
+}
+
+void SubViewportContainer::unhandled_input(const Ref &p_event) {
+ _propagate_nonpositional_event(p_event);
+}
+
+void SubViewportContainer::_propagate_nonpositional_event(const Ref &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (Engine::get_singleton()->is_editor_hint()) {
@@ -262,5 +282,6 @@ void SubViewportContainer::_bind_methods() {
}
SubViewportContainer::SubViewportContainer() {
- set_process_input(true);
+ set_process_unhandled_input(true);
+ set_focus_mode(FOCUS_CLICK);
}
diff --git a/scene/gui/subviewport_container.h b/scene/gui/subviewport_container.h
index 8e5f5d157db9..3c6cd09d6660 100644
--- a/scene/gui/subviewport_container.h
+++ b/scene/gui/subviewport_container.h
@@ -41,6 +41,7 @@ class SubViewportContainer : public Container {
void _notify_viewports(int p_notification);
bool _is_propagated_in_gui_input(const Ref &p_event);
void _send_event_to_viewports(const Ref &p_event);
+ void _propagate_nonpositional_event(const Ref &p_event);
protected:
void _notification(int p_what);
@@ -54,6 +55,7 @@ class SubViewportContainer : public Container {
bool is_stretch_enabled() const;
virtual void input(const Ref &p_event) override;
+ virtual void unhandled_input(const Ref &p_event) override;
virtual void gui_input(const Ref &p_event) override;
void set_stretch_shrink(int p_shrink);
int get_stretch_shrink() const;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 8609b7794460..e0853eb2dbf4 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -3025,18 +3025,18 @@ void Viewport::_push_unhandled_input_internal(const Ref &p_event) {
get_tree()->_call_input_pause(shortcut_input_group, SceneTree::CALL_INPUT_TYPE_SHORTCUT_INPUT, p_event, this);
}
- // Unhandled Input.
- if (!is_input_handled()) {
- ERR_FAIL_COND(!is_inside_tree());
- get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, p_event, this);
- }
-
// Unhandled key Input - Used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, and to handle Unicode input with Alt / Ctrl modifiers after handling shortcuts.
if (!is_input_handled() && (Object::cast_to(*p_event) != nullptr)) {
ERR_FAIL_COND(!is_inside_tree());
get_tree()->_call_input_pause(unhandled_key_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT, p_event, this);
}
+ // Unhandled Input.
+ if (!is_input_handled()) {
+ ERR_FAIL_COND(!is_inside_tree());
+ get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, p_event, this);
+ }
+
if (physics_object_picking && !is_input_handled()) {
if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED &&
(Object::cast_to(*p_event) ||