From 166d45b80fa4fa2ecdc29a12caf418aaec345d0b Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Tue, 8 Apr 2025 22:45:39 +0200 Subject: [PATCH] UI: Padding When Opening Menu When One is Already Open When you open a menu or popover, moving your mouse to a neighboring root menu button will switch to that one. For example when you open the "File" menu and move to the right to have "Edit" open automatically. This currently causes problems with some neighboring menus. This PR adds a safety padding to the open item. This generally means that once you open a menu, you will need to move your mouse into the neighbor's content, not just hit the edge. Pull Request: https://projects.blender.org/blender/blender/pulls/135692 --- .../editors/interface/interface_handlers.cc | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.cc b/source/blender/editors/interface/interface_handlers.cc index 157fe2ca958..257b6392688 100644 --- a/source/blender/editors/interface/interface_handlers.cc +++ b/source/blender/editors/interface/interface_handlers.cc @@ -12039,7 +12039,7 @@ static int ui_handle_region_semi_modal_buttons(bContext *C, const wmEvent *event } /* Return true if we should open another menu while one is already open. */ -static bool ui_can_activate_other_menu(uiBut *but, uiBut *but_other) +static bool ui_can_activate_other_menu(uiBut *but, uiBut *but_other, const wmEvent *event) { if (but_other->flag & UI_BUT_DISABLED) { return false; @@ -12057,7 +12057,42 @@ static bool ui_can_activate_other_menu(uiBut *but, uiBut *but_other) return false; } - return true; + float safety = 4.0f * UI_SCALE_FAC; + if (!but_other->str.empty()) { + safety += 4.0f * UI_SCALE_FAC; + } + + float left, right; + if (but_other->rect.xmin < but->rect.xmin) { + /* Right to Left. */ + if (but->rect.xmin - but_other->rect.xmax > (24.0f * UI_SCALE_FAC)) { + /* If they are far enough part just switch. */ + return true; + } + right = but->rect.xmax; + left = but_other->rect.xmax; + if (ELEM(but_other->type, UI_BTYPE_POPOVER, UI_BTYPE_MENU)) { + /* Skip the dropdown arrow on the right of it. */ + safety += 8.0f * UI_SCALE_FAC; + } + left -= safety; + } + else { + /* Left to Right. */ + if (but_other->rect.xmin - but->rect.xmax > (24.0f * UI_SCALE_FAC)) { + /* If they are far enough part just switch. */ + return true; + } + left = but->rect.xmin; + right = but_other->rect.xmin; + if (but_other->icon && !but_other->str.empty()) { + /* Skip the icon on the left of it. */ + safety += 16.0f * UI_SCALE_FAC; + } + right += safety; + } + + return (event->mval[0] < int(left) || event->mval[0] > int(right)); } /* handle buttons at the window level, modal, for example while @@ -12096,7 +12131,7 @@ static int ui_handler_region_menu(bContext *C, const wmEvent *event, void * /*us { /* if mouse moves to a different root-level menu button, * open it to replace the current menu */ - if (ui_can_activate_other_menu(but, but_other)) { + if (ui_can_activate_other_menu(but, but_other, event)) { ui_handle_button_activate(C, region, but_other, BUTTON_ACTIVATE_OVER); button_activate_state(C, but_other, BUTTON_STATE_MENU_OPEN); retval = WM_UI_HANDLER_BREAK;