diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-02-13 08:18:11 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-02-13 09:02:52 +0300 |
commit | 57d0e4969d45a503102ee91329c695fe86977c02 (patch) | |
tree | df350e4355b8de67646eebf3c20c62d9f969921f /source | |
parent | 60066b0b80f68e8cfc696998bd2cdffaffbe4f4b (diff) |
Fix crash using 'activate_init' in popup menus
Reported in T71112
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/include/UI_interface.h | 5 | ||||
-rw-r--r-- | source/blender/editors/interface/interface.c | 32 |
2 files changed, 30 insertions, 7 deletions
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 3089d980f06..5bed153e995 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -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, diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index 8af8fdb06a1..a7eec8d42cd 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -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; } |