1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-27 15:57:02 +00:00

Fix selecting popup menu items on mouse release

This commit is contained in:
Robert Yevdokimov
2024-01-08 00:07:24 -05:00
parent 89cc635c05
commit 06c2cda848
2 changed files with 53 additions and 48 deletions

View File

@@ -438,6 +438,9 @@ void PopupMenu::_input_from_window(const Ref<InputEvent> &p_event) {
} }
void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) { void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseButton> b = p_event;
Ref<InputEventMouseMotion> m = p_event;
if (!items.is_empty()) { if (!items.is_empty()) {
Input *input = Input::get_singleton(); Input *input = Input::get_singleton();
Ref<InputEventJoypadMotion> joypadmotion_event = p_event; Ref<InputEventJoypadMotion> joypadmotion_event = p_event;
@@ -566,35 +569,44 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
} }
} }
Ref<InputEventMouseButton> b = p_event; if (m.is_valid() && drag_to_press) {
BitField<MouseButtonMask> initial_button_mask = m->get_button_mask();
if (b.is_valid()) { if (!initial_button_mask.has_flag(mouse_button_to_mask(MouseButton::LEFT)) && !initial_button_mask.has_flag(mouse_button_to_mask(MouseButton::RIGHT))) {
if (!item_clickable_area.has_point(b->get_position())) { mouse_is_pressed = false;
return;
} }
MouseButton button_idx = b->get_button_index(); if (!item_clickable_area.has_point(m->get_position()) && !mouse_is_pressed) {
if (!b->is_pressed()) { drag_to_press = false;
// Activate the item on release of either the left mouse button or }
// any mouse button held down when the popup was opened. }
// This allows for opening the popup and triggering an action in a single mouse click.
if (button_idx == MouseButton::LEFT || initial_button_mask.has_flag(mouse_button_to_mask(button_idx))) {
bool was_during_grabbed_click = during_grabbed_click;
during_grabbed_click = false;
initial_button_mask.clear();
// Disable clicks under a time threshold to avoid selection right when opening the popup. if ((b.is_valid() && b->is_pressed()) || (!mouse_is_pressed && drag_to_press)) {
if (b.is_valid()) {
MouseButton button_idx = b->get_button_index();
if (button_idx != MouseButton::LEFT && button_idx != MouseButton::RIGHT) {
return;
}
} else {
uint64_t now = OS::get_singleton()->get_ticks_msec(); uint64_t now = OS::get_singleton()->get_ticks_msec();
uint64_t diff = now - popup_time_msec; uint64_t diff = now - popup_time_msec;
if (diff < 150) { if (diff < 250) {
drag_to_press = false;
return; return;
} }
int over = _get_mouse_over(b->get_position());
if (over < 0) {
if (!was_during_grabbed_click) {
hide();
} }
drag_to_press = false;
int over = -1;
if (m.is_valid()) {
over = _get_mouse_over(m->get_position());
} else if (b.is_valid()) {
over = _get_mouse_over(b->get_position());
}
if (over < 0) {
hide();
return; return;
} }
@@ -608,10 +620,6 @@ void PopupMenu::_input_from_window_internal(const Ref<InputEvent> &p_event) {
} }
activate_item(over); activate_item(over);
} }
}
}
Ref<InputEventMouseMotion> m = p_event;
if (m.is_valid()) { if (m.is_valid()) {
if (m->get_velocity().is_zero_approx()) { if (m->get_velocity().is_zero_approx()) {
@@ -1046,11 +1054,6 @@ void PopupMenu::_notification(int p_what) {
} }
} 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_INTERNAL_PROCESS: { case NOTIFICATION_INTERNAL_PROCESS: {
Input *input = Input::get_singleton(); Input *input = Input::get_singleton();
@@ -2844,6 +2847,8 @@ void PopupMenu::popup(const Rect2i &p_bounds) {
moved = Vector2(); moved = Vector2();
popup_time_msec = OS::get_singleton()->get_ticks_msec(); popup_time_msec = OS::get_singleton()->get_ticks_msec();
Popup::popup(p_bounds); Popup::popup(p_bounds);
drag_to_press = true;
mouse_is_pressed = true;
} }
PopupMenu::PopupMenu() { PopupMenu::PopupMenu() {

View File

@@ -101,8 +101,8 @@ class PopupMenu : public Popup {
Timer *submenu_timer = nullptr; Timer *submenu_timer = nullptr;
List<Rect2> autohide_areas; List<Rect2> autohide_areas;
Vector<Item> items; Vector<Item> items;
BitField<MouseButtonMask> initial_button_mask; bool mouse_is_pressed = true;
bool during_grabbed_click = false; bool drag_to_press = true;
int mouse_over = -1; int mouse_over = -1;
int submenu_over = -1; int submenu_over = -1;
String _get_accel_text(const Item &p_item) const; String _get_accel_text(const Item &p_item) const;