diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2010-08-25 13:33:48 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2010-08-25 13:33:48 +0400 |
commit | 85dcd4c636e6ef68a962d37666412f0cc124f6f6 (patch) | |
tree | 9873ab3b5f9f208fc7ebbde9c8c26a11047db97b /source | |
parent | 155c2d1212720cb162895b1b693609ede92ac498 (diff) |
Fix #23433: crash with undo where a UI button was still active and accessing
data that was freed.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/editors/interface/interface.c | 6 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 22 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 2 |
3 files changed, 17 insertions, 13 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index d1c65fb333c..021dcc940e6 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1765,9 +1765,11 @@ static void ui_free_but(const bContext *C, uiBut *but) } if(but->func_argN) MEM_freeN(but->func_argN); if(but->active) { - /* XXX solve later, buttons should be free-able without context? */ + /* XXX solve later, buttons should be free-able without context ideally, + however they may have open tooltips or popup windows, which need to + be closed using a context pointer */ if(C) - ui_button_active_cancel(C, but); + ui_button_active_free(C, but); else if(but->active) MEM_freeN(but->active); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 8dcc204f06f..ac06f635975 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -4777,7 +4777,7 @@ static void button_activate_init(bContext *C, ARegion *ar, uiBut *but, uiButtonA button_activate_state(C, but, BUTTON_STATE_WAIT_FLASH); } -static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *but, int mousemove) +static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *but, int mousemove, int onfree) { uiBlock *block= but->block; uiBut *bt; @@ -4787,7 +4787,8 @@ static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *b button_activate_state(C, but, BUTTON_STATE_EXIT); /* apply the button action or value */ - ui_apply_button(C, block, but, data, 0); + if(!onfree) + ui_apply_button(C, block, but, data, 0); /* if this button is in a menu, this will set the button return * value to the button value and the menu return value to ok, the @@ -4802,7 +4803,7 @@ static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *b } } - if(!data->cancel) { + if(!onfree && !data->cancel) { /* autokey & undo push */ ui_apply_autokey_undo(C, but); @@ -4835,7 +4836,8 @@ static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *b but->active= NULL; but->flag &= ~(UI_ACTIVE|UI_SELECT); but->flag |= UI_BUT_LAST_ACTIVE; - ui_check_but(but); + if(!onfree) + ui_check_but(but); /* adds empty mousemove in queue for re-init handler, in case mouse is * still over a button. we cannot just check for this ourselfs because @@ -4844,7 +4846,7 @@ static void button_activate_exit(bContext *C, uiHandleButtonData *data, uiBut *b WM_event_add_mousemove(C); } -void ui_button_active_cancel(const bContext *C, uiBut *but) +void ui_button_active_free(const bContext *C, uiBut *but) { uiHandleButtonData *data; @@ -4854,7 +4856,7 @@ void ui_button_active_cancel(const bContext *C, uiBut *but) if(but->active) { data= but->active; data->cancel= 1; - button_activate_exit((bContext*)C, data, but, 0); + button_activate_exit((bContext*)C, data, but, 0, 1); } } @@ -4920,7 +4922,7 @@ static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiBu if(oldbut) { data= oldbut->active; data->cancel= 1; - button_activate_exit(C, data, oldbut, 0); + button_activate_exit(C, data, oldbut, 0, 0); } button_activate_init(C, ar, but, type); @@ -5078,7 +5080,7 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) postbut= data->postbut; posttype= data->posttype; - button_activate_exit(C, data, but, (postbut == NULL)); + button_activate_exit(C, data, but, (postbut == NULL), 0); /* for jumping to the next button with tab while text editing */ if(postbut) @@ -5182,7 +5184,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * if(menu->menuretval != UI_RETURN_OK) data->cancel= 1; - button_activate_exit(C, data, but, 1); + button_activate_exit(C, data, but, 1, 0); } else if(menu->menuretval == UI_RETURN_OUT) { if(event->type==MOUSEMOVE && ui_mouse_inside_button(data->region, but, event->x, event->y)) { @@ -5196,7 +5198,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * } else { data->cancel= 1; - button_activate_exit(C, data, but, 1); + button_activate_exit(C, data, but, 1, 0); } } } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index cb8130573fe..84d6605651b 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -456,7 +456,7 @@ void ui_draw_but_IMAGE(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, rct /* interface_handlers.c */ extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but); -extern void ui_button_active_cancel(const struct bContext *C, uiBut *but); +extern void ui_button_active_free(const struct bContext *C, uiBut *but); extern int ui_button_is_active(struct ARegion *ar); /* interface_widgets.c */ |