UI: fix popover menus not refreshing when changing settings.
This commit is contained in:
parent
a593cc046c
commit
a14005c070
Notes:
blender-bot
2023-02-14 08:06:35 +01:00
Referenced by commit 2d2f23de10
, Fix T55348: Renaming a marker can't cancel
Referenced by issue #55348, Esc while naming marker doesn't work
|
@ -422,10 +422,7 @@ void UI_popup_menu_but_set(uiPopupMenu *pup, struct ARegion *butregion, uiBut *b
|
|||
|
||||
typedef struct uiPopover uiPopover;
|
||||
|
||||
uiPopover *UI_popover_begin(
|
||||
struct bContext *C) ATTR_NONNULL();
|
||||
uiPopover *UI_popover_begin_ex(
|
||||
struct bContext *C, const char *block_name) ATTR_NONNULL();
|
||||
uiPopover *UI_popover_begin(struct bContext *C) ATTR_NONNULL();
|
||||
void UI_popover_end(struct bContext *C, struct uiPopover *head);
|
||||
struct uiLayout *UI_popover_layout(uiPopover *head);
|
||||
|
||||
|
|
|
@ -635,11 +635,8 @@ PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext,
|
|||
|
||||
static void popup_check(bContext *C, wmOperator *op)
|
||||
{
|
||||
if (op && op->type->check && op->type->check(C, op)) {
|
||||
/* check for popup and re-layout buttons */
|
||||
ARegion *ar_menu = CTX_wm_menu(C);
|
||||
if (ar_menu)
|
||||
ED_region_tag_refresh_ui(ar_menu);
|
||||
if (op && op->type->check) {
|
||||
op->type->check(C, op);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -779,7 +776,7 @@ static void ui_apply_but_funcs_after(bContext *C)
|
|||
|
||||
if (after.popup_op)
|
||||
popup_check(C, after.popup_op);
|
||||
|
||||
|
||||
if (after.opptr) {
|
||||
/* free in advance to avoid leak on exit */
|
||||
opptr = *after.opptr;
|
||||
|
@ -7936,8 +7933,9 @@ static void button_activate_exit(
|
|||
WM_cursor_modal_restore(data->window);
|
||||
}
|
||||
|
||||
/* redraw (data is but->active!) */
|
||||
/* redraw and refresh (for popups) */
|
||||
ED_region_tag_redraw(data->region);
|
||||
ED_region_tag_refresh_ui(data->region);
|
||||
|
||||
/* clean up button */
|
||||
if (but->active) {
|
||||
|
@ -8589,13 +8587,8 @@ static int ui_handle_list_event(bContext *C, const wmEvent *event, ARegion *ar,
|
|||
}
|
||||
|
||||
if (redraw) {
|
||||
if (listbox->block->flag & UI_BLOCK_POPUP) {
|
||||
/* popups need special refreshing */
|
||||
ED_region_tag_refresh_ui(ar);
|
||||
}
|
||||
else {
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
ED_region_tag_redraw(ar);
|
||||
ED_region_tag_refresh_ui(ar);
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
|
|
@ -519,16 +519,19 @@ struct uiKeyNavLock {
|
|||
};
|
||||
|
||||
typedef uiBlock * (*uiBlockHandleCreateFunc)(struct bContext *C, struct uiPopupBlockHandle *handle, void *arg1);
|
||||
typedef void (*uiBlockHandleFreeFunc)(struct uiPopupBlockHandle *handle, void *arg1);
|
||||
|
||||
struct uiPopupBlockCreate {
|
||||
uiBlockCreateFunc create_func;
|
||||
uiBlockCreateFunc create_func;
|
||||
uiBlockHandleCreateFunc handle_create_func;
|
||||
uiBlockHandleFreeFunc free_func;
|
||||
void *arg;
|
||||
|
||||
int event_xy[2];
|
||||
|
||||
/* when popup is initialized from a button */
|
||||
ARegion *butregion;
|
||||
uiBut *but;
|
||||
};
|
||||
|
||||
struct uiPopupBlockHandle {
|
||||
|
|
|
@ -74,121 +74,115 @@ struct uiPopover {
|
|||
uiBlock *block;
|
||||
uiLayout *layout;
|
||||
uiBut *but;
|
||||
ARegion *butregion;
|
||||
|
||||
int mx, my;
|
||||
bool popover, slideout;
|
||||
|
||||
uiMenuCreateFunc menu_func;
|
||||
void *menu_arg;
|
||||
};
|
||||
|
||||
static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
|
||||
static void ui_popover_create_block(bContext *C, uiPopover *pup, int opcontext)
|
||||
{
|
||||
uiBlock *block;
|
||||
uiPopover *pup = arg_pup;
|
||||
int minwidth, width, height;
|
||||
uiStyle *style = UI_style_get_dpi();
|
||||
|
||||
if (pup->menu_func) {
|
||||
pup->block->handle = handle;
|
||||
pup->menu_func(C, pup->layout, pup->menu_arg);
|
||||
pup->block->handle = NULL;
|
||||
}
|
||||
pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
|
||||
pup->layout = UI_block_layout(
|
||||
pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0,
|
||||
U.widget_unit * UI_POPOVER_WIDTH_UNITS, 0, MENU_PADDING, style);
|
||||
|
||||
uiLayoutSetOperatorContext(pup->layout, opcontext);
|
||||
|
||||
if (pup->but) {
|
||||
/* minimum width to enforece */
|
||||
minwidth = BLI_rctf_size_x(&pup->but->rect);
|
||||
if (pup->but->context) {
|
||||
uiLayoutContextCopy(pup->layout, pup->but->context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
minwidth = UI_MENU_WIDTH_MIN;
|
||||
/* Some enums reversing is strange, currently we have no good way to
|
||||
* reverse some enum's but not others, so reverse all so the first menu
|
||||
* items are always close to the mouse cursor. */
|
||||
pup->block->flag |= UI_BLOCK_NO_FLIP;
|
||||
}
|
||||
}
|
||||
|
||||
static uiBlock *ui_block_func_POPOVER(bContext *C, uiPopupBlockHandle *handle, void *arg_pup)
|
||||
{
|
||||
uiPopover *pup = arg_pup;
|
||||
|
||||
/* Create UI block and layout now if it wasn't done between begin/end. */
|
||||
if (!pup->layout) {
|
||||
ui_popover_create_block(C, pup, WM_OP_INVOKE_REGION_WIN);
|
||||
|
||||
if (pup->menu_func) {
|
||||
pup->block->handle = handle;
|
||||
pup->menu_func(C, pup->layout, pup->menu_arg);
|
||||
pup->block->handle = NULL;
|
||||
}
|
||||
|
||||
pup->layout = NULL;
|
||||
}
|
||||
|
||||
block = pup->block;
|
||||
|
||||
/* in some cases we create the block before the region,
|
||||
* so we set it delayed here if necessary */
|
||||
if (BLI_findindex(&handle->region->uiblocks, block) == -1)
|
||||
UI_block_region_set(block, handle->region);
|
||||
/* Setup and resolve UI layout for block. */
|
||||
uiBlock *block = pup->block;
|
||||
int width, height;
|
||||
|
||||
UI_block_region_set(block, handle->region);
|
||||
UI_block_layout_resolve(block, &width, &height);
|
||||
|
||||
UI_block_flag_enable(block, UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_KEEP_OPEN | UI_BLOCK_POPOVER);
|
||||
|
||||
UI_block_direction_set(block, UI_DIR_DOWN | UI_DIR_CENTER_X);
|
||||
|
||||
const int block_margin = U.widget_unit / 2;
|
||||
|
||||
if (pup->popover) {
|
||||
if (pup->but) {
|
||||
/* For a header menu we set the direction automatic. */
|
||||
block->minbounds = BLI_rctf_size_x(&pup->but->rect);
|
||||
UI_block_bounds_set_normal(block, block_margin);
|
||||
|
||||
/* If menu slides out of other menu, override direction. */
|
||||
bool slideout = false; //ui_block_is_menu(pup->but->block);
|
||||
if (slideout)
|
||||
UI_block_direction_set(block, UI_DIR_RIGHT);
|
||||
}
|
||||
else {
|
||||
/* Not attached to a button. */
|
||||
int offset[2] = {0, 0}; /* Dummy. */
|
||||
UI_block_flag_enable(block, UI_BLOCK_LOOP);
|
||||
UI_block_direction_set(block, block->direction);
|
||||
block->minbounds = minwidth;
|
||||
block->minbounds = UI_MENU_WIDTH_MIN;
|
||||
UI_block_bounds_set_popup(block, block_margin, offset[0], offset[1]);
|
||||
}
|
||||
else {
|
||||
/* for a header menu we set the direction automatic */
|
||||
block->minbounds = minwidth;
|
||||
UI_block_bounds_set_normal(block, block_margin);
|
||||
}
|
||||
|
||||
/* if menu slides out of other menu, override direction */
|
||||
if (pup->slideout)
|
||||
UI_block_direction_set(block, UI_DIR_RIGHT);
|
||||
return block;
|
||||
}
|
||||
|
||||
return pup->block;
|
||||
static void ui_block_free_func_POPOVER(uiPopupBlockHandle *UNUSED(handle), void *arg_pup)
|
||||
{
|
||||
uiPopover *pup = arg_pup;
|
||||
MEM_freeN(pup);
|
||||
}
|
||||
|
||||
uiPopupBlockHandle *ui_popover_panel_create(
|
||||
bContext *C, ARegion *butregion, uiBut *but,
|
||||
uiMenuCreateFunc menu_func, void *arg)
|
||||
{
|
||||
wmWindow *window = CTX_wm_window(C);
|
||||
uiStyle *style = UI_style_get_dpi();
|
||||
uiPopupBlockHandle *handle;
|
||||
uiPopover *pup;
|
||||
|
||||
pup = MEM_callocN(sizeof(uiPopover), __func__);
|
||||
pup->block = UI_block_begin(C, NULL, __func__, UI_EMBOSS);
|
||||
UI_block_emboss_set(pup->block, UI_EMBOSS);
|
||||
pup->layout = UI_block_layout(
|
||||
pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0,
|
||||
U.widget_unit * UI_POPOVER_WIDTH_UNITS, 0, MENU_PADDING, style);
|
||||
pup->slideout = false; // but ? ui_block_is_menu(but->block) : false;
|
||||
/* Create popover, buttons are created from callback. */
|
||||
uiPopover *pup = MEM_callocN(sizeof(uiPopover), __func__);
|
||||
pup->but = but;
|
||||
uiLayoutSetOperatorContext(pup->layout, WM_OP_INVOKE_REGION_WIN);
|
||||
|
||||
if (!but) {
|
||||
/* no button to start from, means we are a popover */
|
||||
pup->mx = window->eventstate->x;
|
||||
pup->my = window->eventstate->y;
|
||||
pup->popover = true;
|
||||
pup->block->flag |= UI_BLOCK_NO_FLIP;
|
||||
}
|
||||
/* some enums reversing is strange, currently we have no good way to
|
||||
* reverse some enum's but not others, so reverse all so the first menu
|
||||
* items are always close to the mouse cursor */
|
||||
else {
|
||||
if (but->context) {
|
||||
uiLayoutContextCopy(pup->layout, but->context);
|
||||
}
|
||||
}
|
||||
|
||||
/* menu is created from a callback */
|
||||
pup->menu_func = menu_func;
|
||||
pup->menu_arg = arg;
|
||||
|
||||
/* Create popup block. */
|
||||
uiPopupBlockHandle *handle;
|
||||
handle = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup);
|
||||
handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
|
||||
|
||||
/* Add handlers. If attached to a button, the button will already
|
||||
* add a modal handler and pass on events. */
|
||||
if (!but) {
|
||||
handle->popup = true;
|
||||
|
||||
wmWindow *window = CTX_wm_window(C);
|
||||
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
|
||||
WM_event_add_mousemove(C);
|
||||
handle->popup = true;
|
||||
}
|
||||
|
||||
handle->can_refresh = false;
|
||||
MEM_freeN(pup);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
@ -200,20 +194,13 @@ uiPopupBlockHandle *ui_popover_panel_create(
|
|||
|
||||
/**
|
||||
* Only return handler, and set optional title.
|
||||
* \param block_name: Assigned to uiBlock.name (useful info for debugging).
|
||||
*/
|
||||
uiPopover *UI_popover_begin_ex(bContext *C, const char *block_name)
|
||||
uiPopover *UI_popover_begin(bContext *C)
|
||||
{
|
||||
uiStyle *style = UI_style_get_dpi();
|
||||
uiPopover *pup = MEM_callocN(sizeof(uiPopover), "popover menu");
|
||||
|
||||
pup->block = UI_block_begin(C, NULL, block_name, UI_EMBOSS);
|
||||
pup->layout = UI_block_layout(
|
||||
pup->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 0, 0,
|
||||
U.widget_unit * UI_POPOVER_WIDTH_UNITS, 0, MENU_PADDING, style);
|
||||
|
||||
/* Copied from menus, change if needed. */
|
||||
uiLayoutSetOperatorContext(pup->layout, WM_OP_EXEC_REGION_WIN);
|
||||
/* Opertor context default same as menus, change if needed. */
|
||||
ui_popover_create_block(C, pup, WM_OP_EXEC_REGION_WIN);
|
||||
|
||||
/* create in advance so we can let buttons point to retval already */
|
||||
pup->block->handle = MEM_callocN(sizeof(uiPopupBlockHandle), "uiPopupBlockHandle");
|
||||
|
@ -221,47 +208,22 @@ uiPopover *UI_popover_begin_ex(bContext *C, const char *block_name)
|
|||
return pup;
|
||||
}
|
||||
|
||||
uiPopover *UI_popover_begin(bContext *C)
|
||||
{
|
||||
return UI_popover_begin_ex(C, __func__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setting the button makes the popover open from the button instead of the cursor.
|
||||
*/
|
||||
#if 0
|
||||
void UI_popover_panel_but_set(uiPopover *pup, struct ARegion *butregion, uiBut *but)
|
||||
{
|
||||
pup->but = but;
|
||||
pup->butregion = butregion;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set the whole structure to work */
|
||||
void UI_popover_end(bContext *C, uiPopover *pup)
|
||||
{
|
||||
/* Create popup block. No refresh support since the buttons were created
|
||||
* between begin/end and we have no callback to recreate them. */
|
||||
uiPopupBlockHandle *handle;
|
||||
|
||||
handle = ui_popup_block_create(C, NULL, NULL, NULL, ui_block_func_POPOVER, pup);
|
||||
handle->popup_create_vars.free_func = ui_block_free_func_POPOVER;
|
||||
handle->can_refresh = false;
|
||||
|
||||
/* Add handlers. */
|
||||
wmWindow *window = CTX_wm_window(C);
|
||||
uiPopupBlockHandle *menu;
|
||||
uiBut *but = NULL;
|
||||
ARegion *butregion = NULL;
|
||||
|
||||
pup->popover = true;
|
||||
pup->mx = window->eventstate->x;
|
||||
pup->my = window->eventstate->y;
|
||||
|
||||
if (pup->but) {
|
||||
but = pup->but;
|
||||
butregion = pup->butregion;
|
||||
}
|
||||
|
||||
menu = ui_popup_block_create(C, butregion, but, NULL, ui_block_func_POPOVER, pup);
|
||||
menu->popup = true;
|
||||
|
||||
UI_popup_handlers_add(C, &window->modalhandlers, menu, 0);
|
||||
UI_popup_handlers_add(C, &window->modalhandlers, handle, 0);
|
||||
WM_event_add_mousemove(C);
|
||||
|
||||
menu->can_refresh = false;
|
||||
MEM_freeN(pup);
|
||||
handle->popup = true;
|
||||
}
|
||||
|
||||
uiLayout *UI_popover_layout(uiPopover *pup)
|
||||
|
|
|
@ -314,9 +314,11 @@ static void ui_block_region_refresh(const bContext *C, ARegion *ar)
|
|||
ar->do_draw &= ~RGN_DRAW_REFRESH_UI;
|
||||
for (block = ar->uiblocks.first; block; block = block_next) {
|
||||
block_next = block->next;
|
||||
if (block->handle->can_refresh) {
|
||||
handle_ctx_area = block->handle->ctx_area;
|
||||
handle_ctx_region = block->handle->ctx_region;
|
||||
uiPopupBlockHandle *handle = block->handle;
|
||||
|
||||
if (handle->can_refresh) {
|
||||
handle_ctx_area = handle->ctx_area;
|
||||
handle_ctx_region = handle->ctx_region;
|
||||
|
||||
if (handle_ctx_area) {
|
||||
CTX_wm_area_set((bContext *)C, handle_ctx_area);
|
||||
|
@ -324,7 +326,10 @@ static void ui_block_region_refresh(const bContext *C, ARegion *ar)
|
|||
if (handle_ctx_region) {
|
||||
CTX_wm_region_set((bContext *)C, handle_ctx_region);
|
||||
}
|
||||
ui_popup_block_refresh((bContext *)C, block->handle, NULL, NULL);
|
||||
|
||||
uiBut *but = handle->popup_create_vars.but;
|
||||
ARegion *butregion = handle->popup_create_vars.butregion;
|
||||
ui_popup_block_refresh((bContext *)C, handle, butregion, but);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -654,6 +659,7 @@ uiPopupBlockHandle *ui_popup_block_create(
|
|||
handle->popup_create_vars.create_func = create_func;
|
||||
handle->popup_create_vars.handle_create_func = handle_create_func;
|
||||
handle->popup_create_vars.arg = arg;
|
||||
handle->popup_create_vars.but = but;
|
||||
handle->popup_create_vars.butregion = but ? butregion : NULL;
|
||||
copy_v2_v2_int(handle->popup_create_vars.event_xy, &window->eventstate->x);
|
||||
/* caller may free vars used to create this popup, in that case this variable should be disabled. */
|
||||
|
@ -684,6 +690,10 @@ uiPopupBlockHandle *ui_popup_block_create(
|
|||
|
||||
void ui_popup_block_free(bContext *C, uiPopupBlockHandle *handle)
|
||||
{
|
||||
if (handle->popup_create_vars.free_func) {
|
||||
handle->popup_create_vars.free_func(handle, handle->popup_create_vars.arg);
|
||||
}
|
||||
|
||||
ui_popup_block_remove(C, handle);
|
||||
|
||||
MEM_freeN(handle);
|
||||
|
|
Loading…
Reference in New Issue