Fix crash using 'activate_init' in popup menus

Reported in T71112
This commit is contained in:
Campbell Barton 2020-02-13 16:18:11 +11:00
parent 60066b0b80
commit 57d0e4969d
2 changed files with 30 additions and 7 deletions

View File

@ -723,6 +723,11 @@ void UI_but_drawflag_disable(uiBut *but, int flag);
void UI_but_type_set_menu_from_pulldown(uiBut *but);
/* special button case, only draw it when used actively, for outliner etc */
bool UI_but_active_only_ex(const struct bContext *C,
struct ARegion *ar,
uiBlock *block,
uiBut *but,
bool remove_on_failure);
bool UI_but_active_only(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but);
bool UI_block_active_only_flagged_buttons(const struct bContext *C,
struct ARegion *ar,

View File

@ -849,7 +849,8 @@ static bool ui_but_update_from_old_block(const bContext *C,
/* needed for temporarily rename buttons, such as in outliner or file-select,
* they should keep calling uiDefButs to keep them alive */
/* returns 0 when button removed */
bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
bool UI_but_active_only_ex(
const bContext *C, ARegion *ar, uiBlock *block, uiBut *but, const bool remove_on_failure)
{
uiBlock *oldblock;
uiBut *oldbut;
@ -873,27 +874,44 @@ bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *b
ui_but_activate_event((bContext *)C, ar, but);
}
else if ((found == true) && (isactive == false)) {
BLI_remlink(&block->buttons, but);
ui_but_free(C, but);
if (remove_on_failure) {
BLI_remlink(&block->buttons, but);
ui_but_free(C, but);
}
return false;
}
return true;
}
bool UI_but_active_only(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but)
{
return UI_but_active_only_ex(C, ar, block, but, true);
}
bool UI_block_active_only_flagged_buttons(const bContext *C, ARegion *ar, uiBlock *block)
{
bool done = false;
for (uiBut *but = block->buttons.first; but; but = but->next) {
if (!done && ui_but_is_editable(but)) {
if (but->flag & UI_BUT_ACTIVATE_ON_INIT) {
if (UI_but_active_only(C, ar, block, but)) {
if (but->flag & UI_BUT_ACTIVATE_ON_INIT) {
but->flag &= ~UI_BUT_ACTIVATE_ON_INIT;
if (ui_but_is_editable(but)) {
if (UI_but_active_only_ex(C, ar, block, but, false)) {
done = true;
break;
}
}
}
but->flag &= ~UI_BUT_ACTIVATE_ON_INIT;
}
if (done) {
/* Run this in a second pass since it's possible activating the button
* removes the buttons being looped over. */
for (uiBut *but = block->buttons.first; but; but = but->next) {
but->flag &= ~UI_BUT_ACTIVATE_ON_INIT;
}
}
return done;
}