I started toying with this and it struck me as a bit of a rabbit hole. I had in mind to create overloaded operators, so that the user could pass alignment and flags, with the conventional call just setting the defaults and calling forward.
From digging, this gets messy :
outliner_id_remap_invoke → WM_operator_props_dialog_popup → UI_popup_block_ex
UI_popup_block_ex takes function definitions that are called later :
UI_popup_block_ex(
C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data, op )
as
void UI_popup_block_ex(bContext *C,
uiBlockCreateFunc func,
uiBlockHandleFunc popup_func,
uiBlockCancelFunc cancel_func,
void *arg,
wmOperator *op,
eButLabelAlign align,
short flag)
{
wmWindow *window = CTX_wm_window(C);
uiPopupBlockHandle *handle;
handle = ui_popup_block_create(C, NULL, NULL, func, NULL, arg, NULL, align, flag);
ui_popup_block_create does this :
/* store vars to refresh popup (RGN_REFRESH_UI) */
handle->popup_create_vars.create_func = create_func;
handle->popup_create_vars.handle_create_func = handle_create_func;
handle->popup_create_vars.arg = arg;
handle->popup_create_vars.arg_free = arg_free;
handle->popup_create_vars.but = but;
handle->popup_create_vars.butregion = but ? butregion : NULL;
So, I had thought about then adding properties to popup_create_vars to carry the alignment and flags (default or user specified).
From what I can tell, this rabbit hole may stop at ui_popup_block_refresh. It pulls out the create_func :
const uiBlockCreateFunc create_func = handle->popup_create_vars.create_func;
and calls here :
/* create ui block */
if (create_func) {
block = create_func(C, region, arg);
}
else {
block = handle_create_func(C, handle, arg);
}
So I think I can use this to pass in the align and flag values without breaking things.
However, I’m not sure if this is clean enough to pass review or there might be a preferred approach. What do you think?
In summary:
-
Create an overload of WM_operator_props_dialog_popup that adds align and flag parameters. The existing function would pass the existing default values :
int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width)
{
/* retain compatibility with previous behavior if caller has not provided alignment and flag */
WM_operator_props_dialog_popup(
C, op, width, UI_BUT_LABEL_ALIGN_SPLIT_COLUMN, UI_TEMPLATE_OP_PROPS_SHOW_TITLE);
}
with the overload :
int WM_operator_props_dialog_popup(bContext *C, wmOperator *op, int width, eButLabelAlign align, short flag)
{
wmOpPopUp *data = MEM_callocN(sizeof(wmOpPopUp), "WM_operator_props_dialog_popup");
data->op = op;
data->width = width * U.dpi_fac;
/* Actual height depends on the content. */
data->height = 0;
data->free_op = true; /* if this runs and gets registered we may want not to free it */
/* op is not executed until popup OK but is clicked */
UI_popup_block_ex(
C, wm_block_dialog_create, wm_operator_ui_popup_ok, wm_operator_ui_popup_cancel, data, op, align, flag);
return OPERATOR_RUNNING_MODAL;
}
-
Overload UI_popup_block_ex to allow the align and flag values to be passed. Overloading, to allow other call sites to remain unchanged, avoiding breakage. Similar to (1), the original function sets as passes on default values for align and flag, consistent with current behavior.
-
Overload ui_popup_block_create to allow align and flag values to be passed.
If this looks sane, the create_ui_block is where, I think, the next changes would be made, to pass the align and flag values forward.