summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/gui/base_button.cpp39
-rw-r--r--scene/gui/base_button.h8
-rw-r--r--scene/gui/control.cpp1
-rw-r--r--scene/gui/menu_button.cpp9
-rw-r--r--scene/gui/menu_button.h2
-rw-r--r--scene/main/viewport.cpp12
6 files changed, 53 insertions, 18 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index 84e9fc187c..fab0dea804 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -317,14 +317,18 @@ bool BaseButton::is_keep_pressed_outside() const {
void BaseButton::set_shortcut(const Ref<Shortcut> &p_shortcut) {
shortcut = p_shortcut;
- set_process_unhandled_input(shortcut.is_valid());
+ set_process_unhandled_key_input(shortcut.is_valid());
}
Ref<Shortcut> BaseButton::get_shortcut() const {
return shortcut;
}
-void BaseButton::_unhandled_input(Ref<InputEvent> p_event) {
+void BaseButton::_unhandled_key_input(Ref<InputEvent> p_event) {
+ if (!_is_focus_owner_in_shorcut_context()) {
+ return;
+ }
+
if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) {
on_action_event(p_event);
accept_event();
@@ -361,9 +365,34 @@ Ref<ButtonGroup> BaseButton::get_button_group() const {
return button_group;
}
+void BaseButton::set_shortcut_context(Node *p_node) {
+ ERR_FAIL_NULL_MSG(p_node, "Shortcut context node can't be null.");
+ shortcut_context = p_node->get_instance_id();
+}
+
+Node *BaseButton::get_shortcut_context() const {
+ Object *ctx_obj = ObjectDB::get_instance(shortcut_context);
+ Node *ctx_node = Object::cast_to<Node>(ctx_obj);
+
+ return ctx_node;
+}
+
+bool BaseButton::_is_focus_owner_in_shorcut_context() const {
+ if (shortcut_context == ObjectID()) {
+ // No context, therefore global - always "in" context.
+ return true;
+ }
+
+ Node *ctx_node = get_shortcut_context();
+ Control *vp_focus = get_focus_owner();
+
+ // If the context is valid and the viewport focus is valid, check if the context is the focus or is a parent of it.
+ return ctx_node && vp_focus && (ctx_node == vp_focus || ctx_node->is_a_parent_of(vp_focus));
+}
+
void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &BaseButton::_gui_input);
- ClassDB::bind_method(D_METHOD("_unhandled_input"), &BaseButton::_unhandled_input);
+ ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &BaseButton::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed);
ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed);
ClassDB::bind_method(D_METHOD("is_hovered"), &BaseButton::is_hovered);
@@ -387,6 +416,9 @@ void BaseButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_button_group", "button_group"), &BaseButton::set_button_group);
ClassDB::bind_method(D_METHOD("get_button_group"), &BaseButton::get_button_group);
+ ClassDB::bind_method(D_METHOD("set_shortcut_context", "node"), &BaseButton::set_shortcut_context);
+ ClassDB::bind_method(D_METHOD("get_shortcut_context"), &BaseButton::get_shortcut_context);
+
BIND_VMETHOD(MethodInfo("_pressed"));
BIND_VMETHOD(MethodInfo("_toggled", PropertyInfo(Variant::BOOL, "button_pressed")));
@@ -426,6 +458,7 @@ BaseButton::BaseButton() {
set_focus_mode(FOCUS_ALL);
action_mode = ACTION_MODE_BUTTON_RELEASE;
button_mask = BUTTON_MASK_LEFT;
+ shortcut_context = ObjectID();
}
BaseButton::~BaseButton() {
diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h
index 33f19949cd..661801216d 100644
--- a/scene/gui/base_button.h
+++ b/scene/gui/base_button.h
@@ -50,6 +50,7 @@ private:
bool shortcut_in_tooltip;
bool keep_pressed_outside;
Ref<Shortcut> shortcut;
+ ObjectID shortcut_context;
ActionMode action_mode;
struct Status {
@@ -75,9 +76,11 @@ protected:
virtual void toggled(bool p_pressed);
static void _bind_methods();
virtual void _gui_input(Ref<InputEvent> p_event);
- virtual void _unhandled_input(Ref<InputEvent> p_event);
+ virtual void _unhandled_key_input(Ref<InputEvent> p_event);
void _notification(int p_what);
+ bool _is_focus_owner_in_shorcut_context() const;
+
public:
enum DrawMode {
DRAW_NORMAL,
@@ -122,6 +125,9 @@ public:
void set_button_group(const Ref<ButtonGroup> &p_group);
Ref<ButtonGroup> get_button_group() const;
+ void set_shortcut_context(Node *p_node);
+ Node *get_shortcut_context() const;
+
BaseButton();
~BaseButton();
};
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 0381f69bcb..96bf2577a8 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -2729,6 +2729,7 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("minimum_size_changed"), &Control::minimum_size_changed);
BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
+ BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_get_minimum_size"));
MethodInfo get_drag_data = MethodInfo("get_drag_data", PropertyInfo(Variant::VECTOR2, "position"));
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index d65e98ea46..bccea315c4 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -34,6 +34,10 @@
#include "scene/main/window.h"
void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) {
+ if (!_is_focus_owner_in_shorcut_context()) {
+ return;
+ }
+
if (disable_shortcuts) {
return;
}
@@ -43,9 +47,6 @@ void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) {
return;
}
- //bool global_only = (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this));
- //if (popup->activate_item_by_event(p_event, global_only))
- // accept_event();
if (popup->activate_item_by_event(p_event, false)) {
accept_event();
}
@@ -100,7 +101,6 @@ void MenuButton::_notification(int p_what) {
void MenuButton::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_popup"), &MenuButton::get_popup);
- ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &MenuButton::_unhandled_key_input);
ClassDB::bind_method(D_METHOD("_set_items"), &MenuButton::_set_items);
ClassDB::bind_method(D_METHOD("_get_items"), &MenuButton::_get_items);
ClassDB::bind_method(D_METHOD("set_switch_on_hover", "enable"), &MenuButton::set_switch_on_hover);
@@ -123,6 +123,7 @@ MenuButton::MenuButton() {
set_toggle_mode(true);
set_disable_shortcuts(false);
set_process_unhandled_key_input(true);
+ set_enabled_focus_mode(FOCUS_NONE);
set_action_mode(ACTION_MODE_BUTTON_PRESS);
popup = memnew(PopupMenu);
diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h
index 6330899ad3..65b46d5b69 100644
--- a/scene/gui/menu_button.h
+++ b/scene/gui/menu_button.h
@@ -42,7 +42,6 @@ class MenuButton : public Button {
bool disable_shortcuts;
PopupMenu *popup;
- void _unhandled_key_input(Ref<InputEvent> p_event);
Array _get_items() const;
void _set_items(const Array &p_items);
@@ -51,6 +50,7 @@ class MenuButton : public Button {
protected:
void _notification(int p_what);
static void _bind_methods();
+ virtual void _unhandled_key_input(Ref<InputEvent> p_event) override;
public:
virtual void pressed() override;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index f4498507f1..e770dd22e9 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -1804,15 +1804,7 @@ bool Viewport::_gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_che
void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
ERR_FAIL_COND(p_event.is_null());
- //?
- /*
- if (!is_visible()) {
- return; //simple and plain
- }
- */
-
Ref<InputEventMouseButton> mb = p_event;
-
if (mb.is_valid()) {
gui.key_event_accepted = false;
@@ -2000,7 +1992,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
Ref<InputEventMouseMotion> mm = p_event;
-
if (mm.is_valid()) {
gui.key_event_accepted = false;
Point2 mpos = mm->get_position();
@@ -3043,7 +3034,10 @@ void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coor
ev = p_event;
}
+ // Unhandled Input
get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", ev, this);
+
+ // Unhandled key Input - used for performance reasons - This is called a lot less then _unhandled_input since it ignores MouseMotion, etc
if (!is_input_handled() && Object::cast_to<InputEventKey>(*ev) != nullptr) {
get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", ev, this);
}