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.
This commit is contained in:
parent
3fcfbf24b3
commit
aab587817c
Notes:
blender-bot
2023-02-14 11:29:52 +01:00
Referenced by issue #37795, Hard crash when pressing backspace while mouse hovers over Editor-type button.
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue