summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/classes/Node.xml25
-rw-r--r--editor/editor_file_dialog.cpp6
-rw-r--r--editor/editor_file_dialog.h2
-rw-r--r--editor/editor_inspector.cpp4
-rw-r--r--editor/editor_inspector.h2
-rw-r--r--editor/editor_node.cpp4
-rw-r--r--editor/editor_node.h2
-rw-r--r--editor/editor_settings_dialog.cpp6
-rw-r--r--editor/editor_settings_dialog.h2
-rw-r--r--editor/plugins/animation_player_editor_plugin.cpp4
-rw-r--r--editor/plugins/animation_player_editor_plugin.h2
-rw-r--r--editor/plugins/asset_library_editor_plugin.cpp4
-rw-r--r--editor/plugins/asset_library_editor_plugin.h2
-rw-r--r--editor/plugins/canvas_item_editor_plugin.cpp4
-rw-r--r--editor/plugins/canvas_item_editor_plugin.h2
-rw-r--r--editor/plugins/node_3d_editor_plugin.cpp4
-rw-r--r--editor/plugins/node_3d_editor_plugin.h2
-rw-r--r--editor/plugins/script_editor_plugin.cpp4
-rw-r--r--editor/plugins/script_editor_plugin.h2
-rw-r--r--editor/project_manager.cpp4
-rw-r--r--editor/project_manager.h2
-rw-r--r--editor/project_settings_editor.cpp4
-rw-r--r--editor/project_settings_editor.h2
-rw-r--r--editor/scene_tree_dock.cpp4
-rw-r--r--editor/scene_tree_dock.h2
-rw-r--r--scene/gui/base_button.cpp4
-rw-r--r--scene/gui/base_button.h2
-rw-r--r--scene/gui/file_dialog.cpp6
-rw-r--r--scene/gui/file_dialog.h2
-rw-r--r--scene/gui/line_edit.cpp22
-rw-r--r--scene/gui/line_edit.h1
-rw-r--r--scene/gui/menu_button.cpp4
-rw-r--r--scene/gui/menu_button.h2
-rw-r--r--scene/gui/text_edit.cpp16
-rw-r--r--scene/gui/text_edit.h1
-rw-r--r--scene/main/node.cpp46
-rw-r--r--scene/main/node.h7
-rw-r--r--scene/main/scene_tree.cpp3
-rw-r--r--scene/main/scene_tree.h1
-rw-r--r--scene/main/viewport.cpp14
-rw-r--r--scene/main/viewport.h1
41 files changed, 182 insertions, 51 deletions
diff --git a/doc/classes/Node.xml b/doc/classes/Node.xml
index b1a6ed7740..f1e51b6f79 100644
--- a/doc/classes/Node.xml
+++ b/doc/classes/Node.xml
@@ -84,6 +84,17 @@
[b]Note:[/b] [method _ready] may be called only once for each node. After removing a node from the scene tree and adding it again, [code]_ready[/code] will not be called a second time. This can be bypassed by requesting another call with [method request_ready], which may be called anywhere before adding the node again.
</description>
</method>
+ <method name="_shortcut_input" qualifiers="virtual">
+ <return type="void" />
+ <argument index="0" name="event" type="InputEvent" />
+ <description>
+ Called when an [InputEventKey] or [InputEventShortcut] hasn't been consumed by [method _input] or any GUI [Control] item. The input event propagates up through the node tree until a node consumes it.
+ It is only called if shortcut processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process_shortcut_input].
+ To consume the input event and stop it propagating further to other nodes, [method Viewport.set_input_as_handled] can be called.
+ This method can be used to handle shortcuts.
+ [b]Note:[/b] This method is only called if the node is present in the scene tree (i.e. if it's not orphan).
+ </description>
+ </method>
<method name="_unhandled_input" qualifiers="virtual">
<return type="void" />
<argument index="0" name="event" type="InputEvent" />
@@ -102,6 +113,7 @@
Called when an [InputEventKey] or [InputEventShortcut] hasn't been consumed by [method _input] or any GUI [Control] item. The input event propagates up through the node tree until a node consumes it.
It is only called if unhandled key input processing is enabled, which is done automatically if this method is overridden, and can be toggled with [method set_process_unhandled_key_input].
To consume the input event and stop it propagating further to other nodes, [method Viewport.set_input_as_handled] can be called.
+ This method can be used to handle Unicode character input with [kbd]Alt[/kbd], [kbd]Alt + Ctrl[/kbd], and [kbd]Alt + Shift[/kbd] modifiers, after shortcuts were handled.
For gameplay input, this and [method _unhandled_input] are usually a better fit than [method _input] as they allow the GUI to intercept the events first.
[b]Note:[/b] This method is only called if the node is present in the scene tree (i.e. if it's not an orphan).
</description>
@@ -462,6 +474,12 @@
Returns [code]true[/code] if internal processing is enabled (see [method set_process_internal]).
</description>
</method>
+ <method name="is_processing_shortcut_input" qualifiers="const">
+ <return type="bool" />
+ <description>
+ Returns [code]true[/code] if the node is processing shortcuts (see [method set_process_shortcut_input]).
+ </description>
+ </method>
<method name="is_processing_unhandled_input" qualifiers="const">
<return type="bool" />
<description>
@@ -673,6 +691,13 @@
[b]Warning:[/b] Built-in Nodes rely on the internal processing for their own logic, so changing this value from your code may lead to unexpected behavior. Script access to this internal logic is provided for specific advanced uses, but is unsafe and not supported.
</description>
</method>
+ <method name="set_process_shortcut_input">
+ <return type="void" />
+ <argument index="0" name="enable" type="bool" />
+ <description>
+ Enables shortcut processing. Enabled automatically if [method _shortcut_input] is overridden. Any calls to this before [method _ready] will be ignored.
+ </description>
+ </method>
<method name="set_process_unhandled_input">
<return type="void" />
<argument index="0" name="enable" type="bool" />
diff --git a/editor/editor_file_dialog.cpp b/editor/editor_file_dialog.cpp
index ab403c4212..179894915b 100644
--- a/editor/editor_file_dialog.cpp
+++ b/editor/editor_file_dialog.cpp
@@ -106,7 +106,7 @@ void EditorFileDialog::_notification(int p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
if (!is_visible()) {
- set_process_unhandled_input(false);
+ set_process_shortcut_input(false);
}
} break;
@@ -126,7 +126,7 @@ void EditorFileDialog::_notification(int p_what) {
}
}
-void EditorFileDialog::unhandled_input(const Ref<InputEvent> &p_event) {
+void EditorFileDialog::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
Ref<InputEventKey> k = p_event;
@@ -327,7 +327,7 @@ void EditorFileDialog::_post_popup() {
_update_favorites();
}
- set_process_unhandled_input(true);
+ set_process_shortcut_input(true);
}
void EditorFileDialog::_thumbnail_result(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, const Variant &p_udata) {
diff --git a/editor/editor_file_dialog.h b/editor/editor_file_dialog.h
index 07af8c5435..fffe7ffcc5 100644
--- a/editor/editor_file_dialog.h
+++ b/editor/editor_file_dialog.h
@@ -201,7 +201,7 @@ private:
void _thumbnail_done(const String &p_path, const Ref<Texture2D> &p_preview, const Ref<Texture2D> &p_small_preview, const Variant &p_udata);
void _request_single_thumbnail(const String &p_path);
- virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
bool _is_open_should_be_disabled();
diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp
index 1449edb58f..d5085942c3 100644
--- a/editor/editor_inspector.cpp
+++ b/editor/editor_inspector.cpp
@@ -685,7 +685,7 @@ void EditorProperty::gui_input(const Ref<InputEvent> &p_event) {
}
}
-void EditorProperty::unhandled_key_input(const Ref<InputEvent> &p_event) {
+void EditorProperty::shortcut_input(const Ref<InputEvent> &p_event) {
if (!selected || !p_event->is_pressed()) {
return;
}
@@ -971,7 +971,7 @@ EditorProperty::EditorProperty() {
label_reference = nullptr;
bottom_editor = nullptr;
menu = nullptr;
- set_process_unhandled_key_input(true);
+ set_process_shortcut_input(true);
}
void EditorProperty::_update_popup() {
diff --git a/editor/editor_inspector.h b/editor/editor_inspector.h
index c9e8a1672e..c5bcbe0725 100644
--- a/editor/editor_inspector.h
+++ b/editor/editor_inspector.h
@@ -128,7 +128,7 @@ protected:
virtual void _set_read_only(bool p_read_only);
virtual void gui_input(const Ref<InputEvent> &p_event) override;
- virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
const Color *_get_property_colors();
public:
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp
index 52f7366dd7..0cd07333ea 100644
--- a/editor/editor_node.cpp
+++ b/editor/editor_node.cpp
@@ -430,7 +430,7 @@ void EditorNode::_update_title() {
DisplayServer::get_singleton()->window_set_title(title);
}
-void EditorNode::unhandled_input(const Ref<InputEvent> &p_event) {
+void EditorNode::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
Ref<InputEventKey> k = p_event;
@@ -7168,7 +7168,7 @@ EditorNode::EditorNode() {
_update_recent_scenes();
editor_data.restore_editor_global_states();
- set_process_unhandled_input(true);
+ set_process_shortcut_input(true);
load_errors = memnew(RichTextLabel);
load_error_dialog = memnew(AcceptDialog);
diff --git a/editor/editor_node.h b/editor/editor_node.h
index 5f09d4e518..2e0fb19b87 100644
--- a/editor/editor_node.h
+++ b/editor/editor_node.h
@@ -585,7 +585,7 @@ private:
void _exit_editor(int p_exit_code);
- virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
bool has_main_screen() const { return true; }
diff --git a/editor/editor_settings_dialog.cpp b/editor/editor_settings_dialog.cpp
index 285b909b66..dcbe91bd7f 100644
--- a/editor/editor_settings_dialog.cpp
+++ b/editor/editor_settings_dialog.cpp
@@ -92,7 +92,7 @@ void EditorSettingsDialog::popup_edit_settings() {
search_box->grab_focus();
_update_shortcuts();
- set_process_unhandled_input(true);
+ set_process_shortcut_input(true);
// Restore valid window bounds or pop up at default size.
Rect2 saved_size = EditorSettings::get_singleton()->get_project_metadata("dialog_bounds", "editor_settings", Rect2());
@@ -119,7 +119,7 @@ void EditorSettingsDialog::_notification(int p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
if (!is_visible()) {
EditorSettings::get_singleton()->set_project_metadata("dialog_bounds", "editor_settings", Rect2(get_position(), get_size()));
- set_process_unhandled_input(false);
+ set_process_shortcut_input(false);
}
} break;
@@ -148,7 +148,7 @@ void EditorSettingsDialog::_notification(int p_what) {
}
}
-void EditorSettingsDialog::unhandled_input(const Ref<InputEvent> &p_event) {
+void EditorSettingsDialog::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
const Ref<InputEventKey> k = p_event;
diff --git a/editor/editor_settings_dialog.h b/editor/editor_settings_dialog.h
index 42831c9ebd..9a34eac7ef 100644
--- a/editor/editor_settings_dialog.h
+++ b/editor/editor_settings_dialog.h
@@ -82,7 +82,7 @@ class EditorSettingsDialog : public AcceptDialog {
void _settings_property_edited(const String &p_name);
void _settings_save();
- virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
void _notification(int p_what);
void _update_icons();
diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp
index ab8e2ca54a..af7c092d03 100644
--- a/editor/plugins/animation_player_editor_plugin.cpp
+++ b/editor/plugins/animation_player_editor_plugin.cpp
@@ -1267,7 +1267,7 @@ void AnimationPlayerEditor::_onion_skinning_menu(int p_option) {
}
}
-void AnimationPlayerEditor::unhandled_key_input(const Ref<InputEvent> &p_ev) {
+void AnimationPlayerEditor::shortcut_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
Ref<InputEventKey> k = p_ev;
@@ -1750,7 +1750,7 @@ AnimationPlayerEditor::AnimationPlayerEditor(AnimationPlayerEditorPlugin *p_plug
last_active = false;
timeline_position = 0;
- set_process_unhandled_key_input(true);
+ set_process_shortcut_input(true);
add_child(track_editor);
track_editor->set_v_size_flags(SIZE_EXPAND_FILL);
diff --git a/editor/plugins/animation_player_editor_plugin.h b/editor/plugins/animation_player_editor_plugin.h
index 850751e47a..4f6a9c534f 100644
--- a/editor/plugins/animation_player_editor_plugin.h
+++ b/editor/plugins/animation_player_editor_plugin.h
@@ -204,7 +204,7 @@ class AnimationPlayerEditor : public VBoxContainer {
void _animation_key_editor_seek(float p_pos, bool p_drag, bool p_timeline_only = false);
void _animation_key_editor_anim_len_changed(float p_len);
- virtual void unhandled_key_input(const Ref<InputEvent> &p_ev) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_ev) override;
void _animation_tool_menu(int p_option);
void _onion_skinning_menu(int p_option);
diff --git a/editor/plugins/asset_library_editor_plugin.cpp b/editor/plugins/asset_library_editor_plugin.cpp
index 20bd145299..405ece1471 100644
--- a/editor/plugins/asset_library_editor_plugin.cpp
+++ b/editor/plugins/asset_library_editor_plugin.cpp
@@ -640,7 +640,7 @@ void EditorAssetLibrary::_update_repository_options() {
}
}
-void EditorAssetLibrary::unhandled_key_input(const Ref<InputEvent> &p_event) {
+void EditorAssetLibrary::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
const Ref<InputEventKey> key = p_event;
@@ -1541,7 +1541,7 @@ EditorAssetLibrary::EditorAssetLibrary(bool p_templates_only) {
description = nullptr;
set_process(true);
- set_process_unhandled_key_input(true); // Global shortcuts since there is no main element to be focused.
+ set_process_shortcut_input(true); // Global shortcuts since there is no main element to be focused.
downloads_scroll = memnew(ScrollContainer);
downloads_scroll->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
diff --git a/editor/plugins/asset_library_editor_plugin.h b/editor/plugins/asset_library_editor_plugin.h
index 2a04935c47..96830c31fd 100644
--- a/editor/plugins/asset_library_editor_plugin.h
+++ b/editor/plugins/asset_library_editor_plugin.h
@@ -304,7 +304,7 @@ class EditorAssetLibrary : public PanelContainer {
protected:
static void _bind_methods();
void _notification(int p_what);
- virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
public:
void disable_community_support();
diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp
index 764f467192..78307fbe7c 100644
--- a/editor/plugins/canvas_item_editor_plugin.cpp
+++ b/editor/plugins/canvas_item_editor_plugin.cpp
@@ -475,7 +475,7 @@ real_t CanvasItemEditor::snap_angle(real_t p_target, real_t p_start) const {
}
}
-void CanvasItemEditor::unhandled_key_input(const Ref<InputEvent> &p_ev) {
+void CanvasItemEditor::shortcut_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
Ref<InputEventKey> k = p_ev;
@@ -5322,7 +5322,7 @@ CanvasItemEditor::CanvasItemEditor() {
ED_SHORTCUT("canvas_item_editor/zoom_800_percent", TTR("Zoom to 800%"), Key::KEY_4);
ED_SHORTCUT("canvas_item_editor/zoom_1600_percent", TTR("Zoom to 1600%"), Key::KEY_5);
- set_process_unhandled_key_input(true);
+ set_process_shortcut_input(true);
// Update the menus' checkboxes
call_deferred(SNAME("set_state"), get_state());
diff --git a/editor/plugins/canvas_item_editor_plugin.h b/editor/plugins/canvas_item_editor_plugin.h
index 1b61cdc675..26852ea8ed 100644
--- a/editor/plugins/canvas_item_editor_plugin.h
+++ b/editor/plugins/canvas_item_editor_plugin.h
@@ -413,7 +413,7 @@ private:
void _keying_changed();
- virtual void unhandled_key_input(const Ref<InputEvent> &p_ev) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_ev) override;
void _draw_text_at_position(Point2 p_position, String p_string, Side p_side);
void _draw_margin_at_position(int p_value, Point2 p_position, Side p_side);
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp
index eab477adb7..090c140456 100644
--- a/editor/plugins/node_3d_editor_plugin.cpp
+++ b/editor/plugins/node_3d_editor_plugin.cpp
@@ -6848,7 +6848,7 @@ void Node3DEditor::snap_selected_nodes_to_floor() {
}
}
-void Node3DEditor::unhandled_key_input(const Ref<InputEvent> &p_event) {
+void Node3DEditor::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (!is_visible_in_tree()) {
@@ -7893,7 +7893,7 @@ Node3DEditor::Node3DEditor() {
selected = nullptr;
- set_process_unhandled_key_input(true);
+ set_process_shortcut_input(true);
add_to_group("_spatial_editor_group");
EDITOR_DEF("editors/3d/manipulator_gizmo_size", 80);
diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h
index 5447befedd..d5d50c743c 100644
--- a/editor/plugins/node_3d_editor_plugin.h
+++ b/editor/plugins/node_3d_editor_plugin.h
@@ -770,7 +770,7 @@ private:
protected:
void _notification(int p_what);
//void _gui_input(InputEvent p_event);
- virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
static void _bind_methods();
diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp
index 677b55bb88..6f85b24d5e 100644
--- a/editor/plugins/script_editor_plugin.cpp
+++ b/editor/plugins/script_editor_plugin.cpp
@@ -3019,7 +3019,7 @@ void ScriptEditor::input(const Ref<InputEvent> &p_event) {
}
}
-void ScriptEditor::unhandled_key_input(const Ref<InputEvent> &p_event) {
+void ScriptEditor::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (!is_visible_in_tree() || !p_event->is_pressed() || p_event->is_echo()) {
@@ -3740,7 +3740,7 @@ ScriptEditor::ScriptEditor() {
ED_SHORTCUT("script_editor/next_script", TTR("Next Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::PERIOD);
ED_SHORTCUT("script_editor/prev_script", TTR("Previous Script"), KeyModifierMask::CMD | KeyModifierMask::SHIFT | Key::COMMA);
set_process_input(true);
- set_process_unhandled_key_input(true);
+ set_process_shortcut_input(true);
file_menu = memnew(MenuButton);
file_menu->set_text(TTR("File"));
diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h
index 5eeca7a334..5b8d46089e 100644
--- a/editor/plugins/script_editor_plugin.h
+++ b/editor/plugins/script_editor_plugin.h
@@ -426,7 +426,7 @@ class ScriptEditor : public PanelContainer {
void drop_data_fw(const Point2 &p_point, const Variant &p_data, Control *p_from);
virtual void input(const Ref<InputEvent> &p_event) override;
- virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
void _script_list_gui_input(const Ref<InputEvent> &ev);
void _make_script_list_context_menu();
diff --git a/editor/project_manager.cpp b/editor/project_manager.cpp
index cd95f97286..cbc4bb03f6 100644
--- a/editor/project_manager.cpp
+++ b/editor/project_manager.cpp
@@ -1903,7 +1903,7 @@ void ProjectManager::_notification(int p_what) {
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
- set_process_unhandled_key_input(is_visible_in_tree());
+ set_process_shortcut_input(is_visible_in_tree());
} break;
case NOTIFICATION_WM_CLOSE_REQUEST: {
@@ -1962,7 +1962,7 @@ void ProjectManager::_update_project_buttons() {
erase_missing_btn->set_disabled(!_project_list->is_any_project_missing());
}
-void ProjectManager::unhandled_key_input(const Ref<InputEvent> &p_ev) {
+void ProjectManager::shortcut_input(const Ref<InputEvent> &p_ev) {
ERR_FAIL_COND(p_ev.is_null());
Ref<InputEventKey> k = p_ev;
diff --git a/editor/project_manager.h b/editor/project_manager.h
index 4f053793fd..9cea6e163f 100644
--- a/editor/project_manager.h
+++ b/editor/project_manager.h
@@ -126,7 +126,7 @@ class ProjectManager : public Control {
void _install_project(const String &p_zip_path, const String &p_title);
void _dim_window();
- virtual void unhandled_key_input(const Ref<InputEvent> &p_ev) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_ev) override;
void _files_dropped(PackedStringArray p_files, int p_screen);
void _version_button_pressed();
diff --git a/editor/project_settings_editor.cpp b/editor/project_settings_editor.cpp
index 1318287dc8..8aaf3ddbef 100644
--- a/editor/project_settings_editor.cpp
+++ b/editor/project_settings_editor.cpp
@@ -49,7 +49,7 @@ void ProjectSettingsEditor::popup_project_settings() {
_add_feature_overrides();
general_settings_inspector->update_category_list();
- set_process_unhandled_input(true);
+ set_process_shortcut_input(true);
localization_editor->update_translations();
autoload_settings->update_autoload();
@@ -202,7 +202,7 @@ void ProjectSettingsEditor::_select_type(Variant::Type p_type) {
type_box->select(type_box->get_item_index(p_type));
}
-void ProjectSettingsEditor::unhandled_input(const Ref<InputEvent> &p_event) {
+void ProjectSettingsEditor::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
const Ref<InputEventKey> k = p_event;
diff --git a/editor/project_settings_editor.h b/editor/project_settings_editor.h
index c9d849abec..24d61db443 100644
--- a/editor/project_settings_editor.h
+++ b/editor/project_settings_editor.h
@@ -82,7 +82,7 @@ class ProjectSettingsEditor : public AcceptDialog {
void _feature_selected(int p_index);
void _select_type(Variant::Type p_type);
- virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
String _get_setting_name() const;
void _setting_edited(const String &p_name);
diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp
index 551a0ff9c8..32236b01ed 100644
--- a/editor/scene_tree_dock.cpp
+++ b/editor/scene_tree_dock.cpp
@@ -79,7 +79,7 @@ void SceneTreeDock::input(const Ref<InputEvent> &p_event) {
}
}
-void SceneTreeDock::unhandled_key_input(const Ref<InputEvent> &p_event) {
+void SceneTreeDock::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (get_viewport()->gui_get_focus_owner() && get_viewport()->gui_get_focus_owner()->is_text_field()) {
@@ -3476,7 +3476,7 @@ SceneTreeDock::SceneTreeDock(Node *p_scene_root, EditorSelection *p_editor_selec
add_child(quick_open);
quick_open->connect("quick_open", callable_mp(this, &SceneTreeDock::_quick_open));
- set_process_unhandled_key_input(true);
+ set_process_shortcut_input(true);
delete_dialog = memnew(ConfirmationDialog);
add_child(delete_dialog);
diff --git a/editor/scene_tree_dock.h b/editor/scene_tree_dock.h
index 711ac5bc53..599fb01203 100644
--- a/editor/scene_tree_dock.h
+++ b/editor/scene_tree_dock.h
@@ -220,7 +220,7 @@ class SceneTreeDock : public VBoxContainer {
void _nodes_drag_begin();
virtual void input(const Ref<InputEvent> &p_event) override;
- virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
void _import_subscene();
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index ab86face7e..789c01adf3 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -339,14 +339,14 @@ bool BaseButton::is_keep_pressed_outside() const {
void BaseButton::set_shortcut(const Ref<Shortcut> &p_shortcut) {
shortcut = p_shortcut;
- set_process_unhandled_key_input(shortcut.is_valid());
+ set_process_shortcut_input(shortcut.is_valid());
}
Ref<Shortcut> BaseButton::get_shortcut() const {
return shortcut;
}
-void BaseButton::unhandled_key_input(const Ref<InputEvent> &p_event) {
+void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (!_is_focus_owner_in_shortcut_context()) {
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index a2b6ee0845..f4f9b88868 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -77,7 +77,7 @@ protected:
virtual void toggled(bool p_pressed);
static void _bind_methods();
virtual void gui_input(const Ref<InputEvent> &p_event) override;
- virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
void _notification(int p_what);
bool _is_focus_owner_in_shortcut_context() const;
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index e71ab64535..5e74658470 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -95,7 +95,7 @@ void FileDialog::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_VISIBILITY_CHANGED: {
if (!is_visible()) {
- set_process_unhandled_input(false);
+ set_process_shortcut_input(false);
}
} break;
@@ -119,7 +119,7 @@ void FileDialog::_notification(int p_what) {
}
}
-void FileDialog::unhandled_input(const Ref<InputEvent> &p_event) {
+void FileDialog::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
Ref<InputEventKey> k = p_event;
@@ -217,7 +217,7 @@ void FileDialog::_post_popup() {
tree->grab_focus();
}
- set_process_unhandled_input(true);
+ set_process_shortcut_input(true);
// For open dir mode, deselect all items on file dialog open.
if (mode == FILE_MODE_OPEN_DIR) {
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index 9bba93bb89..b41a08c6c7 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -133,7 +133,7 @@ private:
void _update_drives(bool p_select = true);
- virtual void unhandled_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
bool _is_open_should_be_disabled();
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index e063d3aeba..b3f051bb75 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -215,6 +215,27 @@ void LineEdit::_delete(bool p_word, bool p_all_to_right) {
}
}
+void LineEdit::unhandled_key_input(const Ref<InputEvent> &p_event) {
+ Ref<InputEventKey> k = p_event;
+
+ if (k.is_valid()) {
+ if (!k->is_pressed()) {
+ return;
+ }
+ // Handle Unicode (with modifiers active, process after shortcuts).
+ if (has_focus() && editable && (k->get_unicode() >= 32)) {
+ selection_delete();
+ char32_t ucodestr[2] = { (char32_t)k->get_unicode(), 0 };
+ int prev_len = text.length();
+ insert_text_at_caret(ucodestr);
+ if (text.length() != prev_len) {
+ _text_changed();
+ }
+ accept_event();
+ }
+ }
+}
+
void LineEdit::gui_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
@@ -2445,6 +2466,7 @@ LineEdit::LineEdit(const String &p_placeholder) {
set_focus_mode(FOCUS_ALL);
set_default_cursor_shape(CURSOR_IBEAM);
set_mouse_filter(MOUSE_FILTER_STOP);
+ set_process_unhandled_key_input(true);
caret_blink_timer = memnew(Timer);
add_child(caret_blink_timer, false, INTERNAL_MODE_FRONT);
diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h
index 444c9a1c50..b86ccd6421 100644
--- a/scene/gui/line_edit.h
+++ b/scene/gui/line_edit.h
@@ -202,6 +202,7 @@ private:
protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
virtual void gui_input(const Ref<InputEvent> &p_event) override;
bool _set(const StringName &p_name, const Variant &p_value);
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 7e724e4d71..1feee017c2 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -33,7 +33,7 @@
#include "core/os/keyboard.h"
#include "scene/main/window.h"
-void MenuButton::unhandled_key_input(const Ref<InputEvent> &p_event) {
+void MenuButton::shortcut_input(const Ref<InputEvent> &p_event) {
ERR_FAIL_COND(p_event.is_null());
if (!_is_focus_owner_in_shortcut_context()) {
@@ -232,7 +232,7 @@ MenuButton::MenuButton(const String &p_text) :
set_flat(true);
set_toggle_mode(true);
set_disable_shortcuts(false);
- set_process_unhandled_key_input(true);
+ set_process_shortcut_input(true);
set_focus_mode(FOCUS_NONE);
set_action_mode(ACTION_MODE_BUTTON_PRESS);
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index e3ead9c291..0a6b46c796 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -54,7 +54,7 @@ protected:
bool _get(const StringName &p_name, Variant &r_ret) const;
void _get_property_list(List<PropertyInfo> *p_list) const;
static void _bind_methods();
- virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
+ virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
public:
virtual void pressed() override;
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index 1f49491eb8..86969e3ef4 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -1542,6 +1542,21 @@ void TextEdit::_notification(int p_what) {
}
}
+void TextEdit::unhandled_key_input(const Ref<InputEvent> &p_event) {
+ Ref<InputEventKey> k = p_event;
+
+ if (k.is_valid()) {
+ if (!k->is_pressed()) {
+ return;
+ }
+ // Handle Unicode (with modifiers active, process after shortcuts).
+ if (has_focus() && editable && (k->get_unicode() >= 32)) {
+ handle_unicode_input(k->get_unicode());
+ accept_event();
+ }
+ }
+}
+
void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) {
ERR_FAIL_COND(p_gui_input.is_null());
@@ -6620,6 +6635,7 @@ TextEdit::TextEdit(const String &p_placeholder) {
set_focus_mode(FOCUS_ALL);
_update_caches();
set_default_cursor_shape(CURSOR_IBEAM);
+ set_process_unhandled_key_input(true);
text.set_tab_size(text.get_tab_size());
diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h
index 7d36051a37..b365e9c61c 100644
--- a/scene/gui/text_edit.h
+++ b/scene/gui/text_edit.h
@@ -623,6 +623,7 @@ protected:
public:
/* General overrides. */
+ virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override;
virtual void gui_input(const Ref<InputEvent> &p_gui_input) override;
virtual Size2 get_minimum_size() const override;
virtual bool is_text_field() const override;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 7933045c5f..34bb1cde05 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -79,6 +79,9 @@ void Node::_notification(int p_notification) {
if (data.input) {
add_to_group("_vp_input" + itos(get_viewport()->get_instance_id()));
}
+ if (data.shortcut_input) {
+ add_to_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id()));
+ }
if (data.unhandled_input) {
add_to_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id()));
}
@@ -100,6 +103,9 @@ void Node::_notification(int p_notification) {
if (data.input) {
remove_from_group("_vp_input" + itos(get_viewport()->get_instance_id()));
}
+ if (data.shortcut_input) {
+ remove_from_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id()));
+ }
if (data.unhandled_input) {
remove_from_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id()));
}
@@ -126,6 +132,10 @@ void Node::_notification(int p_notification) {
set_process_input(true);
}
+ if (GDVIRTUAL_IS_OVERRIDDEN(_shortcut_input)) {
+ set_process_shortcut_input(true);
+ }
+
if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_input)) {
set_process_unhandled_input(true);
}
@@ -835,6 +845,26 @@ bool Node::is_processing_input() const {
return data.input;
}
+void Node::set_process_shortcut_input(bool p_enable) {
+ if (p_enable == data.shortcut_input) {
+ return;
+ }
+ data.shortcut_input = p_enable;
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ if (p_enable) {
+ add_to_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id()));
+ } else {
+ remove_from_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id()));
+ }
+}
+
+bool Node::is_processing_shortcut_input() const {
+ return data.shortcut_input;
+}
+
void Node::set_process_unhandled_input(bool p_enable) {
if (p_enable == data.unhandled_input) {
return;
@@ -2615,6 +2645,15 @@ void Node::_call_input(const Ref<InputEvent> &p_event) {
}
input(p_event);
}
+
+void Node::_call_shortcut_input(const Ref<InputEvent> &p_event) {
+ GDVIRTUAL_CALL(_shortcut_input, p_event);
+ if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) {
+ return;
+ }
+ shortcut_input(p_event);
+}
+
void Node::_call_unhandled_input(const Ref<InputEvent> &p_event) {
GDVIRTUAL_CALL(_unhandled_input, p_event);
if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) {
@@ -2622,6 +2661,7 @@ void Node::_call_unhandled_input(const Ref<InputEvent> &p_event) {
}
unhandled_input(p_event);
}
+
void Node::_call_unhandled_key_input(const Ref<InputEvent> &p_event) {
GDVIRTUAL_CALL(_unhandled_key_input, p_event);
if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) {
@@ -2633,6 +2673,9 @@ void Node::_call_unhandled_key_input(const Ref<InputEvent> &p_event) {
void Node::input(const Ref<InputEvent> &p_event) {
}
+void Node::shortcut_input(const Ref<InputEvent> &p_key_event) {
+}
+
void Node::unhandled_input(const Ref<InputEvent> &p_event) {
}
@@ -2694,6 +2737,8 @@ void Node::_bind_methods() {
ClassDB::bind_method(D_METHOD("is_processing"), &Node::is_processing);
ClassDB::bind_method(D_METHOD("set_process_input", "enable"), &Node::set_process_input);
ClassDB::bind_method(D_METHOD("is_processing_input"), &Node::is_processing_input);
+ ClassDB::bind_method(D_METHOD("set_process_shortcut_input", "enable"), &Node::set_process_shortcut_input);
+ ClassDB::bind_method(D_METHOD("is_processing_shortcut_input"), &Node::is_processing_shortcut_input);
ClassDB::bind_method(D_METHOD("set_process_unhandled_input", "enable"), &Node::set_process_unhandled_input);
ClassDB::bind_method(D_METHOD("is_processing_unhandled_input"), &Node::is_processing_unhandled_input);
ClassDB::bind_method(D_METHOD("set_process_unhandled_key_input", "enable"), &Node::set_process_unhandled_key_input);
@@ -2854,6 +2899,7 @@ void Node::_bind_methods() {
GDVIRTUAL_BIND(_ready);
GDVIRTUAL_BIND(_get_configuration_warnings);
GDVIRTUAL_BIND(_input, "event");
+ GDVIRTUAL_BIND(_shortcut_input, "event");
GDVIRTUAL_BIND(_unhandled_input, "event");
GDVIRTUAL_BIND(_unhandled_key_input, "event");
}
diff --git a/scene/main/node.h b/scene/main/node.h
index 1f973a0cb4..57b150e29a 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -136,6 +136,7 @@ private:
bool process_internal = false;
bool input = false;
+ bool shortcut_input = false;
bool unhandled_input = false;
bool unhandled_key_input = false;
@@ -215,11 +216,13 @@ protected:
//call from SceneTree
void _call_input(const Ref<InputEvent> &p_event);
+ void _call_shortcut_input(const Ref<InputEvent> &p_event);
void _call_unhandled_input(const Ref<InputEvent> &p_event);
void _call_unhandled_key_input(const Ref<InputEvent> &p_event);
protected:
virtual void input(const Ref<InputEvent> &p_event);
+ virtual void shortcut_input(const Ref<InputEvent> &p_key_event);
virtual void unhandled_input(const Ref<InputEvent> &p_event);
virtual void unhandled_key_input(const Ref<InputEvent> &p_key_event);
@@ -231,6 +234,7 @@ protected:
GDVIRTUAL0RC(Vector<String>, _get_configuration_warnings)
GDVIRTUAL1(_input, Ref<InputEvent>)
+ GDVIRTUAL1(_shortcut_input, Ref<InputEvent>)
GDVIRTUAL1(_unhandled_input, Ref<InputEvent>)
GDVIRTUAL1(_unhandled_key_input, Ref<InputEvent>)
@@ -395,6 +399,9 @@ public:
void set_process_input(bool p_enable);
bool is_processing_input() const;
+ void set_process_shortcut_input(bool p_enable);
+ bool is_processing_shortcut_input() const;
+
void set_process_unhandled_input(bool p_enable);
bool is_processing_unhandled_input() const;
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index 8eeedf51a9..d005633bb5 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -897,6 +897,9 @@ void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_cal
case CALL_INPUT_TYPE_INPUT:
n->_call_input(p_input);
break;
+ case CALL_INPUT_TYPE_SHORTCUT_INPUT:
+ n->_call_shortcut_input(p_input);
+ break;
case CALL_INPUT_TYPE_UNHANDLED_INPUT:
n->_call_unhandled_input(p_input);
break;
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 0f8cbedb41..705ca6ebd3 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -204,6 +204,7 @@ private:
enum CallInputType {
CALL_INPUT_TYPE_INPUT,
+ CALL_INPUT_TYPE_SHORTCUT_INPUT,
CALL_INPUT_TYPE_UNHANDLED_INPUT,
CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT,
};
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index a38bed71d1..e20287c875 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -2744,11 +2744,18 @@ void Viewport::push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local
ev = p_event;
}
+ // Shortcut Input.
+ if (Object::cast_to<InputEventKey>(*ev) != nullptr || Object::cast_to<InputEventShortcut>(*ev) != nullptr) {
+ get_tree()->_call_input_pause(shortcut_input_group, SceneTree::CALL_INPUT_TYPE_SHORTCUT_INPUT, ev, this);
+ }
+
// Unhandled Input.
- get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, ev, this);
+ if (!is_input_handled()) {
+ get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, ev, this);
+ }
- // Unhandled key Input - used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, etc.
- if (!is_input_handled() && (Object::cast_to<InputEventKey>(*ev) != nullptr || Object::cast_to<InputEventShortcut>(*ev) != nullptr)) {
+ // 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<InputEventKey>(*ev) != nullptr)) {
get_tree()->_call_input_pause(unhandled_key_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT, ev, this);
}
@@ -3879,6 +3886,7 @@ Viewport::Viewport() {
input_group = "_vp_input" + id;
gui_input_group = "_vp_gui_input" + id;
unhandled_input_group = "_vp_unhandled_input" + id;
+ shortcut_input_group = "_vp_shortcut_input" + id;
unhandled_key_input_group = "_vp_unhandled_key_input" + id;
// Window tooltip.
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 80be53fab8..32882fbb68 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -270,6 +270,7 @@ private:
Rect2i to_screen_rect;
StringName input_group;
StringName gui_input_group;
+ StringName shortcut_input_group;
StringName unhandled_input_group;
StringName unhandled_key_input_group;