Merge pull request #42109 from EricEzaM/PR/input-and-shortcuts-rework
Shortcuts rework - fixed issues with input propagation and triggering of unwanted shortcuts.
This commit is contained in:
@@ -317,16 +317,21 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,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);
|
||||
@@ -386,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")));
|
||||
|
||||
@@ -425,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() {
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -2983,6 +2983,7 @@ void Control::_bind_methods() {
|
||||
BIND_VMETHOD(MethodInfo("_structured_text_parser", PropertyInfo(Variant::ARRAY, "args"), PropertyInfo(Variant::STRING, "text")));
|
||||
|
||||
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"));
|
||||
|
||||
@@ -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_focus_mode(FOCUS_NONE);
|
||||
set_action_mode(ACTION_MODE_BUTTON_PRESS);
|
||||
|
||||
popup = memnew(PopupMenu);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user