From 42ddc13033c275be2ef7f08e0185463a8fb8d50e Mon Sep 17 00:00:00 2001 From: Leon Schittek Date: Fri, 24 Nov 2023 23:55:43 +0100 Subject: [PATCH] Fix #95709: Improve pulldown menu corner rounding Improve corner rounding of menus and popup blocks. Pull Request: https://projects.blender.org/blender/blender/pulls/111554 --- .../interface/interface_region_popup.cc | 36 ++++++++++++++++++- .../editors/interface/interface_widgets.cc | 24 +++++++++---- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/interface/interface_region_popup.cc b/source/blender/editors/interface/interface_region_popup.cc index 2a3294a1ee0..849963958fa 100644 --- a/source/blender/editors/interface/interface_region_popup.cc +++ b/source/blender/editors/interface/interface_region_popup.cc @@ -109,6 +109,21 @@ static void ui_popup_block_position(wmWindow *window, } } + /* Trim the popup and its contents to the width of the button if the size difference + * is small. This avoids cases where the rounded corner clips underneath the button. */ + const int delta = BLI_rctf_size_x(&block->rect) - BLI_rctf_size_x(&butrct); + const float max_radius = (0.5f * U.widget_unit); + + if (delta >= 0 && delta < max_radius) { + LISTBASE_FOREACH (uiBut *, bt, &block->buttons) { + /* Only trim the right most buttons in multi-column popovers. */ + if (bt->rect.xmax == block->rect.xmax) { + bt->rect.xmax -= delta; + } + } + block->rect.xmax -= delta; + } + ui_block_to_window_rctf(butregion, but->block, &block->rect, &block->rect); /* Compute direction relative to button, based on available space. */ @@ -339,7 +354,26 @@ static void ui_popup_block_position(wmWindow *window, block->safety.xmin = block->rect.xmin - s2; } } - block->direction = dir1; + + const bool fully_aligned_with_button = BLI_rctf_size_x(&block->rect) <= + BLI_rctf_size_x(&butrct) + 1; + const bool off_screen_left = (block->rect.xmin < 0); + const bool off_screen_right = (block->rect.xmax > win_x); + + if (fully_aligned_with_button) { + /* Popup is neither left or right from the button. */ + dir2 &= ~(UI_DIR_LEFT | UI_DIR_RIGHT); + } + else if (off_screen_left || off_screen_right) { + /* Popup is both left and right from the button. */ + dir2 |= (UI_DIR_LEFT | UI_DIR_RIGHT); + } + + /* Popovers don't need secondary direction. Pulldowns to + * the left or right are currently not supported. */ + const bool no_2nd_dir = (but->type == UI_BTYPE_POPOVER || ui_but_menu_draw_as_popover(but) || + dir1 & (UI_DIR_RIGHT | UI_DIR_LEFT)); + block->direction = no_2nd_dir ? dir1 : (dir1 | dir2); } /* Keep a list of these, needed for pull-down menus. */ diff --git a/source/blender/editors/interface/interface_widgets.cc b/source/blender/editors/interface/interface_widgets.cc index 31711ecf303..2c5f59b1203 100644 --- a/source/blender/editors/interface/interface_widgets.cc +++ b/source/blender/editors/interface/interface_widgets.cc @@ -2775,11 +2775,20 @@ static void widget_menu_back( // rect->ymin -= 4.0; // rect->ymax += 4.0; } - else if (direction == UI_DIR_DOWN) { - roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT); - } - else if (direction == UI_DIR_UP) { - roundboxalign = UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT; + else if (direction & (UI_DIR_DOWN | UI_DIR_UP)) { + if (direction & UI_DIR_DOWN) { + roundboxalign = (UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT); + } + else { + roundboxalign = (UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT); + } + /* Corner rounding based on secondary direction. */ + if (direction & UI_DIR_LEFT) { + roundboxalign |= (UI_CNR_TOP_RIGHT | UI_CNR_BOTTOM_RIGHT); + } + if (direction & UI_DIR_RIGHT) { + roundboxalign |= (UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT); + } } GPU_blend(GPU_BLEND_ALPHA); @@ -4742,10 +4751,11 @@ static int widget_roundbox_set(uiBut *but, rcti *rect) if (but->active && (but->type != UI_BTYPE_POPOVER) && !ui_but_menu_draw_as_popover(but)) { const int direction = ui_but_menu_direction(but); - if (direction == UI_DIR_UP) { + /* Pulldown menus that open above or below a button can have more than one direction. */ + if (direction & UI_DIR_UP) { roundbox &= ~(UI_CNR_TOP_RIGHT | UI_CNR_TOP_LEFT); } - else if (direction == UI_DIR_DOWN) { + else if (direction & UI_DIR_DOWN) { roundbox &= ~(UI_CNR_BOTTOM_RIGHT | UI_CNR_BOTTOM_LEFT); } else if (direction == UI_DIR_LEFT) {