summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Alexsander <michaelalexsander@protonmail.com>2022-01-20 08:44:27 -0300
committerMichael Alexsander <michaelalexsander@protonmail.com>2022-01-25 13:51:56 -0300
commit73c225838fa2e6f3ca3adf328375d1c659dc261b (patch)
treef429f3965516b6042e4219d4ca82e027f5801bca
parent203e07aa39d5b55c8c16842d3e2e628209a063c4 (diff)
Make popup menus focus items automatically when not using the mouse
-rw-r--r--doc/classes/PopupMenu.xml7
-rw-r--r--scene/gui/menu_button.cpp8
-rw-r--r--scene/gui/option_button.cpp9
-rw-r--r--scene/gui/popup_menu.cpp44
4 files changed, 49 insertions, 19 deletions
diff --git a/doc/classes/PopupMenu.xml b/doc/classes/PopupMenu.xml
index 108c674ef7..eb1b0aada7 100644
--- a/doc/classes/PopupMenu.xml
+++ b/doc/classes/PopupMenu.xml
@@ -331,6 +331,13 @@
[b]Note:[/b] The indices of items after the removed item will be shifted by one.
</description>
</method>
+ <method name="set_current_index">
+ <return type="void" />
+ <argument index="0" name="index" type="int" />
+ <description>
+ Sets the currently focused item as the given [code]index[/code].
+ </description>
+ </method>
<method name="set_item_accelerator">
<return type="void" />
<argument index="0" name="index" type="int" />
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index f7805136f9..a985a9d031 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -98,7 +98,13 @@ void MenuButton::pressed() {
popup->set_position(gp);
popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), size));
- popup->take_mouse_focus();
+ // If not triggered by the mouse, start the popup with its first item selected.
+ if (popup->get_item_count() > 0 &&
+ ((get_action_mode() == ActionMode::ACTION_MODE_BUTTON_PRESS && Input::get_singleton()->is_action_just_pressed("ui_accept")) ||
+ (get_action_mode() == ActionMode::ACTION_MODE_BUTTON_RELEASE && Input::get_singleton()->is_action_just_released("ui_accept")))) {
+ popup->set_current_index(0);
+ }
+
popup->popup();
}
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index 90bb316448..db45a13d07 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -179,7 +179,14 @@ void OptionButton::pressed() {
Size2 size = get_size() * get_viewport()->get_canvas_transform().get_scale();
popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
popup->set_size(Size2(size.width, 0));
- popup->set_current_index(current);
+
+ // If not triggered by the mouse, start the popup with the checked item selected.
+ if (popup->get_item_count() > 0 &&
+ ((get_action_mode() == ActionMode::ACTION_MODE_BUTTON_PRESS && Input::get_singleton()->is_action_just_pressed("ui_accept")) ||
+ (get_action_mode() == ActionMode::ACTION_MODE_BUTTON_RELEASE && Input::get_singleton()->is_action_just_released("ui_accept")))) {
+ popup->set_current_index(current > -1 ? current : 0);
+ }
+
popup->popup();
}
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index c9fddc3e17..3b4c6ec931 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -192,7 +192,7 @@ void PopupMenu::_activate_submenu(int p_over) {
Popup *submenu_popup = Object::cast_to<Popup>(n);
ERR_FAIL_COND_MSG(!submenu_popup, "Item subnode is not a Popup: " + items[p_over].submenu + ".");
if (submenu_popup->is_visible()) {
- return; //already visible!
+ return; // Already visible.
}
Ref<StyleBox> style = get_theme_stylebox(SNAME("panel"));
@@ -223,24 +223,33 @@ void PopupMenu::_activate_submenu(int p_over) {
submenu_popup->set_close_on_parent_focus(false);
submenu_popup->set_position(submenu_pos);
submenu_popup->set_as_minsize(); // Shrink the popup size to its contents.
- submenu_popup->popup();
- // Set autohide areas
PopupMenu *submenu_pum = Object::cast_to<PopupMenu>(submenu_popup);
- if (submenu_pum) {
- submenu_pum->take_mouse_focus();
- // Make the position of the parent popup relative to submenu popup
- this_rect.position = this_rect.position - submenu_pum->get_position();
-
- // Autohide area above the submenu item
- submenu_pum->clear_autohide_areas();
- submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2));
-
- // If there is an area below the submenu item, add an autohide area there.
- if (items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset <= control->get_size().height) {
- int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + vsep / 2 + style->get_offset().height;
- submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from));
- }
+ if (!submenu_pum) {
+ submenu_popup->popup();
+ return;
+ }
+
+ // If not triggered by the mouse, start the popup with its first item selected.
+ if (submenu_pum->get_item_count() > 0 && Input::get_singleton()->is_action_just_pressed("ui_accept")) {
+ submenu_pum->set_current_index(0);
+ }
+
+ submenu_pum->popup();
+
+ // Set autohide areas.
+
+ // Make the position of the parent popup relative to submenu popup.
+ this_rect.position = this_rect.position - submenu_pum->get_position();
+
+ // Autohide area above the submenu item.
+ submenu_pum->clear_autohide_areas();
+ submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y, this_rect.size.x, items[p_over]._ofs_cache + scroll_offset + style->get_offset().height - vsep / 2));
+
+ // If there is an area below the submenu item, add an autohide area there.
+ if (items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset <= control->get_size().height) {
+ int from = items[p_over]._ofs_cache + items[p_over]._height_cache + scroll_offset + vsep / 2 + style->get_offset().height;
+ submenu_pum->add_autohide_area(Rect2(this_rect.position.x, this_rect.position.y + from, this_rect.size.x, this_rect.size.y - from));
}
}
@@ -1747,6 +1756,7 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_item_tooltip", "index"), &PopupMenu::get_item_tooltip);
ClassDB::bind_method(D_METHOD("get_item_shortcut", "index"), &PopupMenu::get_item_shortcut);
+ ClassDB::bind_method(D_METHOD("set_current_index", "index"), &PopupMenu::set_current_index);
ClassDB::bind_method(D_METHOD("get_current_index"), &PopupMenu::get_current_index);
ClassDB::bind_method(D_METHOD("set_item_count", "count"), &PopupMenu::set_item_count);
ClassDB::bind_method(D_METHOD("get_item_count"), &PopupMenu::get_item_count);