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) ||