Fix sub-menu keyboard navigation.
This commit is contained in:
parent
895f2a21f4
commit
8b0761d1fd
5 changed files with 19 additions and 11 deletions
|
@ -3062,7 +3062,7 @@ void DisplayServerX11::_dispatch_input_event(const Ref<InputEvent> &p_event) {
|
||||||
Callable::CallError ce;
|
Callable::CallError ce;
|
||||||
|
|
||||||
{
|
{
|
||||||
List<WindowID>::Element *E = popup_list.front();
|
List<WindowID>::Element *E = popup_list.back();
|
||||||
if (E && Object::cast_to<InputEventKey>(*p_event)) {
|
if (E && Object::cast_to<InputEventKey>(*p_event)) {
|
||||||
// Redirect keyboard input to active popup.
|
// Redirect keyboard input to active popup.
|
||||||
if (windows.has(E->get())) {
|
if (windows.has(E->get())) {
|
||||||
|
|
|
@ -326,7 +326,7 @@ void DisplayServerOSX::_dispatch_input_event(const Ref<InputEvent> &p_event) {
|
||||||
Callable::CallError ce;
|
Callable::CallError ce;
|
||||||
|
|
||||||
{
|
{
|
||||||
List<WindowID>::Element *E = popup_list.front();
|
List<WindowID>::Element *E = popup_list.back();
|
||||||
if (E && Object::cast_to<InputEventKey>(*p_event)) {
|
if (E && Object::cast_to<InputEventKey>(*p_event)) {
|
||||||
// Redirect keyboard input to active popup.
|
// Redirect keyboard input to active popup.
|
||||||
if (windows.has(E->get())) {
|
if (windows.has(E->get())) {
|
||||||
|
|
|
@ -2003,7 +2003,7 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event)
|
||||||
Callable::CallError ce;
|
Callable::CallError ce;
|
||||||
|
|
||||||
{
|
{
|
||||||
List<WindowID>::Element *E = popup_list.front();
|
List<WindowID>::Element *E = popup_list.back();
|
||||||
if (E && Object::cast_to<InputEventKey>(*p_event)) {
|
if (E && Object::cast_to<InputEventKey>(*p_event)) {
|
||||||
// Redirect keyboard input to active popup.
|
// Redirect keyboard input to active popup.
|
||||||
if (windows.has(E->get())) {
|
if (windows.has(E->get())) {
|
||||||
|
|
|
@ -169,7 +169,7 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopupMenu::_activate_submenu(int p_over) {
|
void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
|
||||||
Node *n = get_node(items[p_over].submenu);
|
Node *n = get_node(items[p_over].submenu);
|
||||||
ERR_FAIL_COND_MSG(!n, "Item subnode does not exist: " + items[p_over].submenu + ".");
|
ERR_FAIL_COND_MSG(!n, "Item subnode does not exist: " + items[p_over].submenu + ".");
|
||||||
Popup *submenu_popup = Object::cast_to<Popup>(n);
|
Popup *submenu_popup = Object::cast_to<Popup>(n);
|
||||||
|
@ -213,8 +213,10 @@ void PopupMenu::_activate_submenu(int p_over) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
submenu_pum->activated_by_keyboard = p_by_keyboard;
|
||||||
|
|
||||||
// If not triggered by the mouse, start the popup with its first item selected.
|
// 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")) {
|
if (submenu_pum->get_item_count() > 0 && p_by_keyboard) {
|
||||||
submenu_pum->set_current_index(0);
|
submenu_pum->set_current_index(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,14 +325,14 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
|
||||||
set_input_as_handled();
|
set_input_as_handled();
|
||||||
}
|
}
|
||||||
} else if (p_event->is_action("ui_right") && p_event->is_pressed()) {
|
} else if (p_event->is_action("ui_right") && p_event->is_pressed()) {
|
||||||
if (mouse_over >= 0 && mouse_over < items.size() && !!items[mouse_over].separator && items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
|
if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && !items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
|
||||||
_activate_submenu(mouse_over);
|
_activate_submenu(mouse_over, true);
|
||||||
set_input_as_handled();
|
set_input_as_handled();
|
||||||
}
|
}
|
||||||
} else if (p_event->is_action("ui_accept") && p_event->is_pressed()) {
|
} else if (p_event->is_action("ui_accept") && p_event->is_pressed()) {
|
||||||
if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) {
|
if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator) {
|
||||||
if (!items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
|
if (!items[mouse_over].submenu.is_empty() && submenu_over != mouse_over) {
|
||||||
_activate_submenu(mouse_over);
|
_activate_submenu(mouse_over, true);
|
||||||
} else {
|
} else {
|
||||||
activate_item(mouse_over);
|
activate_item(mouse_over);
|
||||||
}
|
}
|
||||||
|
@ -396,6 +398,11 @@ void PopupMenu::gui_input(const Ref<InputEvent> &p_event) {
|
||||||
Ref<InputEventMouseMotion> m = p_event;
|
Ref<InputEventMouseMotion> m = p_event;
|
||||||
|
|
||||||
if (m.is_valid()) {
|
if (m.is_valid()) {
|
||||||
|
if (m->get_velocity().is_equal_approx(Vector2())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activated_by_keyboard = false;
|
||||||
|
|
||||||
for (const Rect2 &E : autohide_areas) {
|
for (const Rect2 &E : autohide_areas) {
|
||||||
if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E.has_point(m->get_position())) {
|
if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E.has_point(m->get_position())) {
|
||||||
_close_pressed();
|
_close_pressed();
|
||||||
|
@ -687,7 +694,7 @@ void PopupMenu::_draw_background() {
|
||||||
void PopupMenu::_minimum_lifetime_timeout() {
|
void PopupMenu::_minimum_lifetime_timeout() {
|
||||||
close_allowed = true;
|
close_allowed = true;
|
||||||
// If the mouse still isn't in this popup after timer expires, close.
|
// If the mouse still isn't in this popup after timer expires, close.
|
||||||
if (!get_visible_rect().has_point(get_mouse_position())) {
|
if (!activated_by_keyboard && !get_visible_rect().has_point(get_mouse_position())) {
|
||||||
_close_pressed();
|
_close_pressed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -772,7 +779,7 @@ void PopupMenu::_notification(int p_what) {
|
||||||
|
|
||||||
case NOTIFICATION_INTERNAL_PROCESS: {
|
case NOTIFICATION_INTERNAL_PROCESS: {
|
||||||
// Only used when using operating system windows.
|
// Only used when using operating system windows.
|
||||||
if (!is_embedded() && autohide_areas.size()) {
|
if (!activated_by_keyboard && !is_embedded() && autohide_areas.size()) {
|
||||||
Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
|
Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
|
||||||
mouse_pos -= get_position();
|
mouse_pos -= get_position();
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ class PopupMenu : public Popup {
|
||||||
};
|
};
|
||||||
|
|
||||||
bool close_allowed = false;
|
bool close_allowed = false;
|
||||||
|
bool activated_by_keyboard = false;
|
||||||
|
|
||||||
Timer *minimum_lifetime_timer = nullptr;
|
Timer *minimum_lifetime_timer = nullptr;
|
||||||
Timer *submenu_timer = nullptr;
|
Timer *submenu_timer = nullptr;
|
||||||
|
@ -107,7 +108,7 @@ class PopupMenu : public Popup {
|
||||||
void _shape_item(int p_item);
|
void _shape_item(int p_item);
|
||||||
|
|
||||||
virtual void gui_input(const Ref<InputEvent> &p_event);
|
virtual void gui_input(const Ref<InputEvent> &p_event);
|
||||||
void _activate_submenu(int p_over);
|
void _activate_submenu(int p_over, bool p_by_keyboard = false);
|
||||||
void _submenu_timeout();
|
void _submenu_timeout();
|
||||||
|
|
||||||
uint64_t popup_time_msec = 0;
|
uint64_t popup_time_msec = 0;
|
||||||
|
|
Loading…
Reference in a new issue