diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-12-19 18:04:01 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-12-19 18:07:09 +0400 |
commit | aab587817c55f5c53672efe3b1fc4a0e953cb97e (patch) | |
tree | f7c7cd10964f7fdeb8256f47b3b56e81c5f8f528 | |
parent | 3fcfbf24b3c58eb0ed6e319027b347deea940a42 (diff) |
Fix T37795: Resetting a button to the default value could crash
Added ui_handle_afterfunc_add_operator so a button can queue an operator
to run without executing it immediately.
-rw-r--r-- | source/blender/editors/interface/interface.c | 20 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 43 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_intern.h | 3 |
3 files changed, 53 insertions, 13 deletions
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index d09b3dea98a..b1c66a65c35 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2055,15 +2055,23 @@ bool ui_set_but_string(bContext *C, uiBut *but, const char *str) return false; } -void ui_set_but_default(bContext *C, const bool all) +void ui_set_but_default(bContext *C, const bool all, const bool use_afterfunc) { const char *opstring = "UI_OT_reset_default_button"; - PointerRNA ptr; - WM_operator_properties_create(&ptr, opstring); - RNA_boolean_set(&ptr, "all", all); - WM_operator_name_call(C, opstring, WM_OP_EXEC_DEFAULT, &ptr); - WM_operator_properties_free(&ptr); + if (use_afterfunc) { + PointerRNA *ptr; + wmOperatorType *ot = WM_operatortype_find(opstring, 0); + ptr = ui_handle_afterfunc_add_operator(ot, WM_OP_EXEC_DEFAULT, true); + RNA_boolean_set(ptr, "all", all); + } + else { + PointerRNA ptr; + WM_operator_properties_create(&ptr, opstring); + RNA_boolean_set(&ptr, "all", all); + WM_operator_name_call(C, opstring, WM_OP_EXEC_DEFAULT, &ptr); + WM_operator_properties_free(&ptr); + } } static double soft_range_round_up(double value, double max) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 8a4f89af4a3..f44595d6af6 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -398,6 +398,40 @@ bool ui_is_but_utf8(const uiBut *but) static ListBase UIAfterFuncs = {NULL, NULL}; +static uiAfterFunc *ui_afterfunc_new(void) +{ + uiAfterFunc *after; + + after = MEM_callocN(sizeof(uiAfterFunc), "uiAfterFunc"); + + BLI_addtail(&UIAfterFuncs, after); + + return after; +} + +/** + * For executing operators after the button is pressed. + * (some non operator buttons need to trigger operators), see: [#37795] + * + * \note Can only call while handling buttons. + */ +PointerRNA *ui_handle_afterfunc_add_operator(wmOperatorType *ot, int opcontext, bool create_props) +{ + PointerRNA *ptr = NULL; + uiAfterFunc *after = ui_afterfunc_new(); + + after->optype = ot; + after->opcontext = opcontext; + + if (create_props) { + ptr = MEM_callocN(sizeof(PointerRNA), __func__); + WM_operator_properties_create_ptr(ptr, ot); + after->opptr = ptr; + } + + return ptr; +} + static void ui_apply_but_func(bContext *C, uiBut *but) { uiAfterFunc *after; @@ -410,7 +444,7 @@ static void ui_apply_but_func(bContext *C, uiBut *but) if (but->func || but->funcN || block->handle_func || but->rename_func || (but->type == BUTM && block->butm_func) || but->optype || but->rnaprop) { - after = MEM_callocN(sizeof(uiAfterFunc), "uiAfterFunc"); + after = ui_afterfunc_new(); if (but->func && ELEM(but, but->func_arg1, but->func_arg2)) { /* exception, this will crash due to removed button otherwise */ @@ -452,8 +486,6 @@ static void ui_apply_but_func(bContext *C, uiBut *but) but->optype = NULL; but->opcontext = 0; but->opptr = NULL; - - BLI_addtail(&UIAfterFuncs, after); } } @@ -477,9 +509,8 @@ static void ui_apply_undo(uiBut *but) } /* delayed, after all other funcs run, popups are closed, etc */ - after = MEM_callocN(sizeof(uiAfterFunc), "uiAfterFunc"); + after = ui_afterfunc_new(); BLI_strncpy(after->undostr, str, sizeof(after->undostr)); - BLI_addtail(&UIAfterFuncs, after); } } @@ -5840,7 +5871,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * (event->type == BACKSPACEKEY && event->val == KM_PRESS)) { /* ctrl+backspace = reset active button; backspace = reset a whole array*/ - ui_set_but_default(C, !event->ctrl); + ui_set_but_default(C, !event->ctrl, true); ED_region_tag_redraw(data->region); retval = WM_UI_HANDLER_BREAK; } diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index afdcd7abc54..e11b93ca69b 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -393,7 +393,7 @@ extern bool ui_set_but_string(struct bContext *C, uiBut *but, const char *str); extern bool ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char *str, double *value); extern int ui_get_but_string_max_length(uiBut *but); -extern void ui_set_but_default(struct bContext *C, const bool all); +extern void ui_set_but_default(struct bContext *C, const bool all, const bool use_afterfunc); extern void ui_check_but(uiBut *but); extern bool ui_is_but_float(const uiBut *but); @@ -515,6 +515,7 @@ void ui_draw_but_TRACKPREVIEW(ARegion *ar, uiBut *but, struct uiWidgetColors *wc void ui_draw_but_NODESOCKET(ARegion *ar, uiBut *but, struct uiWidgetColors *wcol, const rcti *rect); /* interface_handlers.c */ +PointerRNA *ui_handle_afterfunc_add_operator(struct wmOperatorType *ot, int opcontext, bool create_props); extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val); extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but); extern void ui_button_execute_do(struct bContext *C, struct ARegion *ar, uiBut *but); |