From 8f69c914080a7fe9555f7126362f08c368a8069d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 2 Dec 2021 15:46:14 +1100 Subject: Fix T93410: Crash hiding a region from Python used by a popover Close all active buttons when hiding a region as this can be called from Python a popover is open from that region. Failure to do this causes the popover to read from the freed button. Also rename UI_screen_free_active_but to UI_screen_free_active_but_highlight since it only frees highlighted buttons. --- source/blender/editors/include/UI_interface.h | 4 +++- source/blender/editors/interface/interface_handlers.c | 18 +++++++++++++++--- source/blender/editors/interface/interface_ops.c | 2 +- source/blender/editors/screen/area.c | 6 ++++++ source/blender/editors/screen/screen_edit.c | 2 +- 5 files changed, 26 insertions(+), 6 deletions(-) (limited to 'source') diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 1dbb486ad72..023a1a64daf 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -735,7 +735,9 @@ void UI_block_set_search_only(uiBlock *block, bool search_only); void UI_block_free(const struct bContext *C, uiBlock *block); void UI_blocklist_free(const struct bContext *C, struct ARegion *region); void UI_blocklist_free_inactive(const struct bContext *C, struct ARegion *region); -void UI_screen_free_active_but(const struct bContext *C, struct bScreen *screen); + +void UI_screen_free_active_but_highlight(const struct bContext *C, struct bScreen *screen); +void UI_region_free_active_but_all(struct bContext *context, struct ARegion *region); void UI_block_region_set(uiBlock *block, struct ARegion *region); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index fe540c3624c..14df5ec68ac 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -439,11 +439,11 @@ typedef struct uiHandleButtonData { float ungrab_mval[2]; #endif - /* menu open (watch UI_screen_free_active_but) */ + /* Menu open, see: #UI_screen_free_active_but_highlight. */ uiPopupBlockHandle *menu; int menuretval; - /* search box (watch UI_screen_free_active_but) */ + /* Search box see: #UI_screen_free_active_but_highlight. */ ARegion *searchbox; #ifdef USE_KEYNAV_LIMIT struct uiKeyNavLock searchbox_keynav_state; @@ -11674,8 +11674,20 @@ bool UI_textbutton_activate_but(const bContext *C, uiBut *actbut) /** \name Public Utilities * \{ */ +void UI_region_free_active_but_all(bContext *C, ARegion *region) +{ + LISTBASE_FOREACH (uiBlock *, block, ®ion->uiblocks) { + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + if (but->active == NULL) { + continue; + } + ui_but_active_free(C, but); + } + } +} + /* is called by notifier */ -void UI_screen_free_active_but(const bContext *C, bScreen *screen) +void UI_screen_free_active_but_highlight(const bContext *C, bScreen *screen) { wmWindow *win = CTX_wm_window(C); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index e1fd7386408..03422e8f520 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -1408,7 +1408,7 @@ static int editsource_exec(bContext *C, wmOperator *op) int ret; /* needed else the active button does not get tested */ - UI_screen_free_active_but(C, CTX_wm_screen(C)); + UI_screen_free_active_but_highlight(C, CTX_wm_screen(C)); // printf("%s: begin\n", __func__); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index 0190e7b7cee..dc7cbb96e96 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -2119,6 +2119,12 @@ void ED_region_visibility_change_update(bContext *C, ScrArea *area, ARegion *reg { if (region->flag & RGN_FLAG_HIDDEN) { WM_event_remove_handlers(C, ®ion->handlers); + /* Needed to close any open pop-overs which would otherwise remain open, + * crashing on attempting to refresh. See: T93410. + * + * When #ED_area_init frees buttons via #UI_blocklist_free a NULL context + * is passed, causing the free not to remove menus or their handlers. */ + UI_region_free_active_but_all(C, region); } ED_area_init(CTX_wm_manager(C), CTX_wm_window(C), area); diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index 3c8fb2e7446..92151ea01b3 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -955,7 +955,7 @@ void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2]) * because it can undo setting the right button as active due * to delayed notifier handling. */ if (C) { - UI_screen_free_active_but(C, screen); + UI_screen_free_active_but_highlight(C, screen); } } } -- cgit v1.2.3