summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRémi Verschelde <rverschelde@gmail.com>2024-02-14 10:59:40 +0100
committerRémi Verschelde <rverschelde@gmail.com>2024-02-14 10:59:40 +0100
commit92951b0295822904f0d656f2d93ab81db4f0f507 (patch)
tree786a21599b11069db67915ca794a6960405c4954
parenta33a87d535eb8de753d586cd33f3d6a7dc872f7f (diff)
parent06c2cda848b4bca8ee2f54a09417a97a7c1384d3 (diff)
downloadredot-engine-92951b0295822904f0d656f2d93ab81db4f0f507.tar.gz
Merge pull request #86952 from ryevdokimov/fix-selecting-popup-menu-items-on-mouse-release
Fix selecting popup menu items on mouse release
-rw-r--r--scene/gui/popup_menu.cpp91
-rw-r--r--scene/gui/popup_menu.h4
2 files changed, 50 insertions, 45 deletions
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index 0da5093ab8..90d962ccfd 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -456,6 +456,9 @@ void PopupMenu::_input_from_window(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()) {
Input *input = Input::get_singleton();
Ref<InputEventJoypadMotion> joypadmotion_event = p_event;
@@ -584,52 +587,57 @@ 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 (!initial_button_mask.has_flag(mouse_button_to_mask(MouseButton::LEFT)) && !initial_button_mask.has_flag(mouse_button_to_mask(MouseButton::RIGHT))) {
+ mouse_is_pressed = false;
+ }
- if (b.is_valid()) {
- if (!item_clickable_area.has_point(b->get_position())) {
- return;
+ if (!item_clickable_area.has_point(m->get_position()) && !mouse_is_pressed) {
+ drag_to_press = false;
}
+ }
- MouseButton button_idx = b->get_button_index();
- if (!b->is_pressed()) {
- // 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.
- uint64_t now = OS::get_singleton()->get_ticks_msec();
- uint64_t diff = now - popup_time_msec;
- if (diff < 150) {
- return;
- }
+ 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 diff = now - popup_time_msec;
+ if (diff < 250) {
+ drag_to_press = false;
+ return;
+ }
+ }
- int over = _get_mouse_over(b->get_position());
- if (over < 0) {
- if (!was_during_grabbed_click) {
- hide();
- }
- return;
- }
+ drag_to_press = false;
- if (items[over].separator || items[over].disabled) {
- return;
- }
+ int over = -1;
- if (!items[over].submenu.is_empty()) {
- _activate_submenu(over);
- return;
- }
- activate_item(over);
- }
+ if (m.is_valid()) {
+ over = _get_mouse_over(m->get_position());
+ } else if (b.is_valid()) {
+ over = _get_mouse_over(b->get_position());
}
- }
- Ref<InputEventMouseMotion> m = p_event;
+ if (over < 0) {
+ hide();
+ return;
+ }
+
+ if (items[over].separator || items[over].disabled) {
+ return;
+ }
+
+ if (!items[over].submenu.is_empty()) {
+ _activate_submenu(over);
+ return;
+ }
+ activate_item(over);
+ }
if (m.is_valid()) {
if (m->get_velocity().is_zero_approx()) {
@@ -1062,11 +1070,6 @@ void PopupMenu::_notification(int p_what) {
}
} 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: {
Input *input = Input::get_singleton();
@@ -2802,6 +2805,8 @@ void PopupMenu::popup(const Rect2i &p_bounds) {
moved = Vector2();
popup_time_msec = OS::get_singleton()->get_ticks_msec();
Popup::popup(p_bounds);
+ drag_to_press = true;
+ mouse_is_pressed = true;
}
PopupMenu::PopupMenu() {
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index d068418059..abe852a993 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -107,8 +107,8 @@ class PopupMenu : public Popup {
Timer *submenu_timer = nullptr;
List<Rect2> autohide_areas;
Vector<Item> items;
- BitField<MouseButtonMask> initial_button_mask;
- bool during_grabbed_click = false;
+ bool mouse_is_pressed = true;
+ bool drag_to_press = true;
int mouse_over = -1;
int submenu_over = -1;
String _get_accel_text(const Item &p_item) const;