You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-10 13:00:37 +00:00
Merge pull request #17809 from RandomShaper/menu-item-on-release
Improve popup menus usability
This commit is contained in:
@@ -1672,8 +1672,6 @@ bool CanvasItemEditor::_gui_input_select(const Ref<InputEvent> &p_event) {
|
|||||||
selection_menu_additive_selection = b->get_shift();
|
selection_menu_additive_selection = b->get_shift();
|
||||||
selection_menu->set_global_position(b->get_global_position());
|
selection_menu->set_global_position(b->get_global_position());
|
||||||
selection_menu->popup();
|
selection_menu->popup();
|
||||||
selection_menu->call_deferred("grab_click_focus");
|
|
||||||
selection_menu->set_invalidate_click_until_motion();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2769,8 +2769,6 @@ void ShaderGraphEditor::_popup_requested(const Vector2 &p_position)
|
|||||||
popup->set_global_position(p_position);
|
popup->set_global_position(p_position);
|
||||||
popup->set_size( Size2( 200, 0) );
|
popup->set_size( Size2( 200, 0) );
|
||||||
popup->popup();
|
popup->popup();
|
||||||
popup->call_deferred("grab_click_focus");
|
|
||||||
popup->set_invalidate_click_until_motion();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderGraphEditor::_notification(int p_what) {
|
void ShaderGraphEditor::_notification(int p_what) {
|
||||||
|
|||||||
@@ -886,8 +886,6 @@ void SpatialEditorViewport::_list_select(Ref<InputEventMouseButton> b) {
|
|||||||
|
|
||||||
selection_menu->set_global_position(b->get_global_position());
|
selection_menu->set_global_position(b->get_global_position());
|
||||||
selection_menu->popup();
|
selection_menu->popup();
|
||||||
selection_menu->call_deferred("grab_click_focus");
|
|
||||||
selection_menu->set_invalidate_click_until_motion();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,6 @@ void MenuButton::pressed() {
|
|||||||
popup->set_size(Size2(size.width, 0));
|
popup->set_size(Size2(size.width, 0));
|
||||||
popup->set_parent_rect(Rect2(Point2(gp - popup->get_global_position()), get_size()));
|
popup->set_parent_rect(Rect2(Point2(gp - popup->get_global_position()), get_size()));
|
||||||
popup->popup();
|
popup->popup();
|
||||||
popup->set_invalidate_click_until_motion();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MenuButton::_gui_input(Ref<InputEvent> p_event) {
|
void MenuButton::_gui_input(Ref<InputEvent> p_event) {
|
||||||
@@ -109,7 +108,6 @@ MenuButton::MenuButton() {
|
|||||||
add_child(popup);
|
add_child(popup);
|
||||||
popup->set_as_toplevel(true);
|
popup->set_as_toplevel(true);
|
||||||
popup->set_pass_on_modal_close_click(false);
|
popup->set_pass_on_modal_close_click(false);
|
||||||
connect("button_up", popup, "call_deferred", make_binds("grab_click_focus"));
|
|
||||||
set_process_unhandled_key_input(true);
|
set_process_unhandled_key_input(true);
|
||||||
set_action_mode(ACTION_MODE_BUTTON_PRESS);
|
set_action_mode(ACTION_MODE_BUTTON_PRESS);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,7 +284,8 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
|
|||||||
if (b->is_pressed())
|
if (b->is_pressed())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (b->get_button_index()) {
|
int button_idx = b->get_button_index();
|
||||||
|
switch (button_idx) {
|
||||||
|
|
||||||
case BUTTON_WHEEL_DOWN: {
|
case BUTTON_WHEEL_DOWN: {
|
||||||
|
|
||||||
@@ -298,30 +299,37 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
|
|||||||
_scroll(b->get_factor(), b->get_position());
|
_scroll(b->get_factor(), b->get_position());
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case BUTTON_LEFT: {
|
default: {
|
||||||
|
// Allow activating item by releasing the LMB or any that was down when the popup appeared
|
||||||
|
if (button_idx == BUTTON_LEFT || (initial_button_mask & (1 << (button_idx - 1)))) {
|
||||||
|
|
||||||
int over = _get_mouse_over(b->get_position());
|
bool was_during_grabbed_click = during_grabbed_click;
|
||||||
|
during_grabbed_click = false;
|
||||||
|
|
||||||
if (invalidated_click) {
|
int over = _get_mouse_over(b->get_position());
|
||||||
invalidated_click = false;
|
|
||||||
break;
|
if (invalidated_click) {
|
||||||
|
invalidated_click = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (over < 0) {
|
||||||
|
if (!was_during_grabbed_click) {
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
break; //non-activable
|
||||||
|
}
|
||||||
|
|
||||||
|
if (items[over].separator || items[over].disabled)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (items[over].submenu != "") {
|
||||||
|
|
||||||
|
_activate_submenu(over);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activate_item(over);
|
||||||
}
|
}
|
||||||
if (over < 0) {
|
}
|
||||||
hide();
|
|
||||||
break; //non-activable
|
|
||||||
}
|
|
||||||
|
|
||||||
if (items[over].separator || items[over].disabled)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (items[over].submenu != "") {
|
|
||||||
|
|
||||||
_activate_submenu(over);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
activate_item(over);
|
|
||||||
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//update();
|
//update();
|
||||||
@@ -503,6 +511,11 @@ void PopupMenu::_notification(int p_what) {
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case NOTIFICATION_POST_POPUP: {
|
||||||
|
|
||||||
|
initial_button_mask = Input::get_singleton()->get_mouse_button_mask();
|
||||||
|
during_grabbed_click = (bool)initial_button_mask;
|
||||||
|
} break;
|
||||||
case NOTIFICATION_POPUP_HIDE: {
|
case NOTIFICATION_POPUP_HIDE: {
|
||||||
|
|
||||||
if (mouse_over >= 0) {
|
if (mouse_over >= 0) {
|
||||||
@@ -1216,15 +1229,20 @@ void PopupMenu::_bind_methods() {
|
|||||||
ADD_SIGNAL(MethodInfo("index_pressed", PropertyInfo(Variant::INT, "index")));
|
ADD_SIGNAL(MethodInfo("index_pressed", PropertyInfo(Variant::INT, "index")));
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupMenu::set_invalidate_click_until_motion() {
|
void PopupMenu::popup(const Rect2 &p_bounds) {
|
||||||
|
|
||||||
|
grab_click_focus();
|
||||||
moved = Vector2();
|
moved = Vector2();
|
||||||
invalidated_click = true;
|
invalidated_click = true;
|
||||||
|
Popup::popup(p_bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
PopupMenu::PopupMenu() {
|
PopupMenu::PopupMenu() {
|
||||||
|
|
||||||
mouse_over = -1;
|
mouse_over = -1;
|
||||||
submenu_over = -1;
|
submenu_over = -1;
|
||||||
|
initial_button_mask = 0;
|
||||||
|
during_grabbed_click = false;
|
||||||
|
|
||||||
set_focus_mode(FOCUS_ALL);
|
set_focus_mode(FOCUS_ALL);
|
||||||
set_as_toplevel(true);
|
set_as_toplevel(true);
|
||||||
|
|||||||
@@ -78,6 +78,8 @@ class PopupMenu : public Popup {
|
|||||||
Timer *submenu_timer;
|
Timer *submenu_timer;
|
||||||
List<Rect2> autohide_areas;
|
List<Rect2> autohide_areas;
|
||||||
Vector<Item> items;
|
Vector<Item> items;
|
||||||
|
int initial_button_mask;
|
||||||
|
bool during_grabbed_click;
|
||||||
int mouse_over;
|
int mouse_over;
|
||||||
int submenu_over;
|
int submenu_over;
|
||||||
Rect2 parent_rect;
|
Rect2 parent_rect;
|
||||||
@@ -178,7 +180,6 @@ public:
|
|||||||
void add_autohide_area(const Rect2 &p_area);
|
void add_autohide_area(const Rect2 &p_area);
|
||||||
void clear_autohide_areas();
|
void clear_autohide_areas();
|
||||||
|
|
||||||
void set_invalidate_click_until_motion();
|
|
||||||
void set_hide_on_item_selection(bool p_enabled);
|
void set_hide_on_item_selection(bool p_enabled);
|
||||||
bool is_hide_on_item_selection() const;
|
bool is_hide_on_item_selection() const;
|
||||||
|
|
||||||
@@ -188,6 +189,8 @@ public:
|
|||||||
void set_hide_on_multistate_item_selection(bool p_enabled);
|
void set_hide_on_multistate_item_selection(bool p_enabled);
|
||||||
bool is_hide_on_multistate_item_selection() const;
|
bool is_hide_on_multistate_item_selection() const;
|
||||||
|
|
||||||
|
virtual void popup(const Rect2 &p_bounds = Rect2());
|
||||||
|
|
||||||
PopupMenu();
|
PopupMenu();
|
||||||
~PopupMenu();
|
~PopupMenu();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -181,6 +181,7 @@ public:
|
|||||||
Viewport::GUI::GUI() {
|
Viewport::GUI::GUI() {
|
||||||
|
|
||||||
mouse_focus = NULL;
|
mouse_focus = NULL;
|
||||||
|
mouse_click_grabber = NULL;
|
||||||
mouse_focus_button = -1;
|
mouse_focus_button = -1;
|
||||||
key_focus = NULL;
|
key_focus = NULL;
|
||||||
mouse_over = NULL;
|
mouse_over = NULL;
|
||||||
@@ -2278,7 +2279,7 @@ List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) {
|
|||||||
else
|
else
|
||||||
p_control->_modal_set_prev_focus_owner(0);
|
p_control->_modal_set_prev_focus_owner(0);
|
||||||
|
|
||||||
if (gui.mouse_focus && !p_control->is_a_parent_of(gui.mouse_focus)) {
|
if (gui.mouse_focus && !p_control->is_a_parent_of(gui.mouse_focus) && !gui.mouse_click_grabber) {
|
||||||
Ref<InputEventMouseButton> mb;
|
Ref<InputEventMouseButton> mb;
|
||||||
mb.instance();
|
mb.instance();
|
||||||
mb->set_position(gui.mouse_focus->get_local_mouse_position());
|
mb->set_position(gui.mouse_focus->get_local_mouse_position());
|
||||||
@@ -2300,9 +2301,22 @@ Control *Viewport::_gui_get_focus_owner() {
|
|||||||
|
|
||||||
void Viewport::_gui_grab_click_focus(Control *p_control) {
|
void Viewport::_gui_grab_click_focus(Control *p_control) {
|
||||||
|
|
||||||
|
gui.mouse_click_grabber = p_control;
|
||||||
|
call_deferred("_post_gui_grab_click_focus");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Viewport::_post_gui_grab_click_focus() {
|
||||||
|
|
||||||
|
Control *focus_grabber = gui.mouse_click_grabber;
|
||||||
|
if (!focus_grabber) {
|
||||||
|
// Redundant grab requests were made
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gui.mouse_click_grabber = NULL;
|
||||||
|
|
||||||
if (gui.mouse_focus) {
|
if (gui.mouse_focus) {
|
||||||
|
|
||||||
if (gui.mouse_focus == p_control)
|
if (gui.mouse_focus == focus_grabber)
|
||||||
return;
|
return;
|
||||||
Ref<InputEventMouseButton> mb;
|
Ref<InputEventMouseButton> mb;
|
||||||
mb.instance();
|
mb.instance();
|
||||||
@@ -2313,9 +2327,9 @@ void Viewport::_gui_grab_click_focus(Control *p_control) {
|
|||||||
mb->set_position(click);
|
mb->set_position(click);
|
||||||
mb->set_button_index(gui.mouse_focus_button);
|
mb->set_button_index(gui.mouse_focus_button);
|
||||||
mb->set_pressed(false);
|
mb->set_pressed(false);
|
||||||
gui.mouse_focus->call_deferred(SceneStringNames::get_singleton()->_gui_input, mb);
|
gui.mouse_focus->call_multilevel(SceneStringNames::get_singleton()->_gui_input, mb);
|
||||||
|
|
||||||
gui.mouse_focus = p_control;
|
gui.mouse_focus = focus_grabber;
|
||||||
gui.focus_inv_xform = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse();
|
gui.focus_inv_xform = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse();
|
||||||
click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos);
|
click = gui.mouse_focus->get_global_transform_with_canvas().affine_inverse().xform(gui.last_mouse_pos);
|
||||||
mb->set_position(click);
|
mb->set_position(click);
|
||||||
@@ -2648,6 +2662,7 @@ void Viewport::_bind_methods() {
|
|||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip);
|
ClassDB::bind_method(D_METHOD("_gui_show_tooltip"), &Viewport::_gui_show_tooltip);
|
||||||
ClassDB::bind_method(D_METHOD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
|
ClassDB::bind_method(D_METHOD("_gui_remove_focus"), &Viewport::_gui_remove_focus);
|
||||||
|
ClassDB::bind_method(D_METHOD("_post_gui_grab_click_focus"), &Viewport::_post_gui_grab_click_focus);
|
||||||
|
|
||||||
ClassDB::bind_method(D_METHOD("set_shadow_atlas_size", "size"), &Viewport::set_shadow_atlas_size);
|
ClassDB::bind_method(D_METHOD("set_shadow_atlas_size", "size"), &Viewport::set_shadow_atlas_size);
|
||||||
ClassDB::bind_method(D_METHOD("get_shadow_atlas_size"), &Viewport::get_shadow_atlas_size);
|
ClassDB::bind_method(D_METHOD("get_shadow_atlas_size"), &Viewport::get_shadow_atlas_size);
|
||||||
|
|||||||
@@ -248,6 +248,7 @@ private:
|
|||||||
|
|
||||||
bool key_event_accepted;
|
bool key_event_accepted;
|
||||||
Control *mouse_focus;
|
Control *mouse_focus;
|
||||||
|
Control *mouse_click_grabber;
|
||||||
int mouse_focus_button;
|
int mouse_focus_button;
|
||||||
Control *key_focus;
|
Control *key_focus;
|
||||||
Control *mouse_over;
|
Control *mouse_over;
|
||||||
@@ -323,6 +324,7 @@ private:
|
|||||||
bool _gui_control_has_focus(const Control *p_control);
|
bool _gui_control_has_focus(const Control *p_control);
|
||||||
void _gui_control_grab_focus(Control *p_control);
|
void _gui_control_grab_focus(Control *p_control);
|
||||||
void _gui_grab_click_focus(Control *p_control);
|
void _gui_grab_click_focus(Control *p_control);
|
||||||
|
void _post_gui_grab_click_focus();
|
||||||
void _gui_accept_event();
|
void _gui_accept_event();
|
||||||
|
|
||||||
Control *_gui_get_focus_owner();
|
Control *_gui_get_focus_owner();
|
||||||
|
|||||||
Reference in New Issue
Block a user