diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-05-06 15:32:03 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-05-06 15:40:21 +0300 |
commit | b9bb752e0e852ddc87e42673caf290283137ec04 (patch) | |
tree | da9d7ba6c4168a0ec0653d2e20d443668ccc69fa /source/blender | |
parent | 5461c7526abdd38318d097986220d7006fe5e586 (diff) |
UI: search menus from all visible areas when using the edit menu
Without this, only actions in the top-bar were visible
which isn't very useful.
Now menus are extracted from the areas used in the active window,
unless this search is activated by the key shortcut,
in this case the current area is used.
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/editors/interface/interface_template_search_menu.c | 459 |
1 files changed, 304 insertions, 155 deletions
diff --git a/source/blender/editors/interface/interface_template_search_menu.c b/source/blender/editors/interface/interface_template_search_menu.c index 3d07da083e8..c256923e7fd 100644 --- a/source/blender/editors/interface/interface_template_search_menu.c +++ b/source/blender/editors/interface/interface_template_search_menu.c @@ -64,6 +64,12 @@ /* Unicode arrow. */ #define MENU_SEP "\xe2\x96\xb6" +struct MenuSearch_Context { + int space_type_ui_index; + ScrArea *area; + ARegion *region; +}; + struct MenuSearch_Parent { struct MenuSearch_Parent *parent; MenuType *parent_mt; @@ -107,6 +113,12 @@ struct MenuSearch_Item { int enum_value; } rna; }; + + /** + * Set when we need each menu item to be able to set it's own context. + * may be NULL. + */ + struct MenuSearch_Context *wm_context; }; struct MenuSearch_Data { @@ -143,7 +155,8 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d MemArena *memarena, struct MenuType *mt, const char *drawstr_submenu, - uiBut *but) + uiBut *but, + struct MenuSearch_Context *wm_context) { struct MenuSearch_Item *item = NULL; if (but->optype != NULL) { @@ -187,6 +200,9 @@ static bool menu_items_from_ui_create_item_from_button(struct MenuSearch_Data *d item->state = (but->flag & (UI_BUT_DISABLED | UI_BUT_INACTIVE | UI_BUT_REDALERT)); item->mt = mt; item->drawstr_submenu = drawstr_submenu ? strdup_memarena(memarena, drawstr_submenu) : NULL; + + item->wm_context = wm_context; + BLI_addtail(&data->items, item); return true; } @@ -289,6 +305,8 @@ static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *d item->drawwstr_full = strdup_memarena(memarena, uiname); + item->wm_context = NULL; + BLI_addtail(&operator_items, item); } } @@ -304,10 +322,8 @@ static void menu_items_from_all_operators(bContext *C, struct MenuSearch_Data *d * - Look-up pre-defined editor-menus. * - Look-up key-map items which call menus. */ -static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C, - wmWindow *win, - ScrArea *area, - ARegion *region) +static struct MenuSearch_Data *menu_items_from_ui_create( + bContext *C, wmWindow *win, ScrArea *area_init, ARegion *region_init, bool include_all_areas) { MemArena *memarena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__); /** Map (#MenuType to #MenuSearch_Parent) */ @@ -344,17 +360,113 @@ static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C, } } - /* Populate menus from the editors, - * note that we could create a fake header, draw the header and extract the menus - * from the buttons, however this is quite involved and can be avoided as by convention - * each space-type has a single root-menu that headers use. */ - { - const char *idname_array[] = { - "TOPBAR_MT_editor_menus", - /* Optional second menu for the space-type. */ - NULL, - }; - int idname_array_len = 1; + /* Collect contexts, one for each 'ui_type'. */ + struct MenuSearch_Context *wm_contexts = NULL; + + const EnumPropertyItem *space_type_ui_items = NULL; + int space_type_ui_items_len; + bool space_type_ui_items_free = false; + + /* Types match, cycle the subtype. */ + + if (include_all_areas) { + /* First create arrays for ui_type. */ + PropertyRNA *prop_ui_type; + { + PointerRNA ptr; + RNA_pointer_create(NULL, &RNA_Area, NULL, &ptr); + prop_ui_type = RNA_struct_find_property(&ptr, "ui_type"); + RNA_property_enum_items(C, + &ptr, + prop_ui_type, + &space_type_ui_items, + &space_type_ui_items_len, + &space_type_ui_items_free); + + wm_contexts = BLI_memarena_alloc(memarena, sizeof(*wm_contexts) * space_type_ui_items_len); + + for (int i = 0; i < space_type_ui_items_len; i++) { + wm_contexts[i].space_type_ui_index = -1; + wm_contexts[i].area = NULL; + wm_contexts[i].region = NULL; + } + } + + bScreen *screen = WM_window_get_active_screen(win); + LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) { + ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_WINDOW); + if (region != NULL) { + PointerRNA ptr; + RNA_pointer_create(&screen->id, &RNA_Area, area, &ptr); + const int space_type_ui = RNA_property_enum_get(&ptr, prop_ui_type); + + int space_type_ui_index = RNA_enum_from_value(space_type_ui_items, space_type_ui); + if (space_type_ui_index == -1) { + continue; + } + + if (wm_contexts[space_type_ui_index].space_type_ui_index != -1) { + ScrArea *area_best = wm_contexts[area->spacetype].area; + const uint value_best = (uint)area_best->winx * (uint)area_best->winy; + const uint value_test = (uint)area->winx * (uint)area->winy; + if (value_best > value_test) { + continue; + } + } + + wm_contexts[space_type_ui_index].space_type_ui_index = space_type_ui_index; + wm_contexts[space_type_ui_index].area = area; + wm_contexts[space_type_ui_index].region = region; + } + } + } + + GHashIterator iter; + + for (int space_type_ui_index = -1; space_type_ui_index < space_type_ui_items_len; + space_type_ui_index += 1) { + + ScrArea *area = NULL; + ARegion *region = NULL; + struct MenuSearch_Context *wm_context = NULL; + + if (include_all_areas) { + if (space_type_ui_index == -1) { + /* First run without any context, to populate the top-bar without. */ + wm_context = NULL; + area = NULL; + region = NULL; + } + else { + wm_context = &wm_contexts[space_type_ui_index]; + if (wm_context->space_type_ui_index == -1) { + continue; + } + + area = wm_context->area; + region = wm_context->region; + + CTX_wm_area_set(C, area); + CTX_wm_region_set(C, region); + } + } + else { + area = area_init; + region = region_init; + } + + /* Populate menus from the editors, + * note that we could create a fake header, draw the header and extract the menus + * from the buttons, however this is quite involved and can be avoided as by convention + * each space-type has a single root-menu that headers use. */ + { + const char *idname_array[2] = {NULL}; + int idname_array_len = 0; + + /* Use negative for global (no area) context, populate the top-bar. */ + if (space_type_ui_index == -1) { + idname_array[idname_array_len++] = "TOPBAR_MT_editor_menus"; + } #define SPACE_MENU_MAP(space_type, menu_id) \ case space_type: \ @@ -364,177 +476,180 @@ static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C, case space_type: \ break - if (area != NULL) { - switch (area->spacetype) { - SPACE_MENU_MAP(SPACE_VIEW3D, "VIEW3D_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_GRAPH, "GRAPH_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_OUTLINER, "OUTLINER_MT_editor_menus"); - SPACE_MENU_NOP(SPACE_PROPERTIES); - SPACE_MENU_MAP(SPACE_FILE, "FILE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_IMAGE, "IMAGE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_INFO, "INFO_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_SEQ, "SEQUENCER_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_TEXT, "TEXT_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_ACTION, "DOPESHEET_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_NLA, "NLA_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_NODE, "NODE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_CONSOLE, "CONSOLE_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_USERPREF, "USERPREF_MT_editor_menus"); - SPACE_MENU_MAP(SPACE_CLIP, - (((const SpaceClip *)area->spacedata.first)->mode == SC_MODE_TRACKING) ? - "CLIP_MT_tracking_editor_menus" : - "CLIP_MT_masking_editor_menus"); - SPACE_MENU_NOP(SPACE_TOPBAR); - SPACE_MENU_NOP(SPACE_STATUSBAR); - default: - printf("Unknown space type '%d'\n", area->spacetype); + if (area != NULL) { + switch (area->spacetype) { + SPACE_MENU_MAP(SPACE_VIEW3D, "VIEW3D_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_GRAPH, "GRAPH_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_OUTLINER, "OUTLINER_MT_editor_menus"); + SPACE_MENU_NOP(SPACE_PROPERTIES); + SPACE_MENU_MAP(SPACE_FILE, "FILE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_IMAGE, "IMAGE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_INFO, "INFO_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_SEQ, "SEQUENCER_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_TEXT, "TEXT_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_ACTION, "DOPESHEET_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_NLA, "NLA_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_NODE, "NODE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_CONSOLE, "CONSOLE_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_USERPREF, "USERPREF_MT_editor_menus"); + SPACE_MENU_MAP(SPACE_CLIP, + (((const SpaceClip *)area->spacedata.first)->mode == SC_MODE_TRACKING) ? + "CLIP_MT_tracking_editor_menus" : + "CLIP_MT_masking_editor_menus"); + SPACE_MENU_NOP(SPACE_TOPBAR); + SPACE_MENU_NOP(SPACE_STATUSBAR); + default: + printf("Unknown space type '%d'\n", area->spacetype); + } } - } - for (int i = 0; i < idname_array_len; i++) { - MenuType *mt = WM_menutype_find(idname_array[i], false); - if (mt != NULL) { - BLI_linklist_prepend(&menu_stack, mt); - BLI_gset_add(menu_tagged, mt); + for (int i = 0; i < idname_array_len; i++) { + MenuType *mt = WM_menutype_find(idname_array[i], false); + if (mt != NULL) { + /* Check if this exists because of 'include_all_areas'. */ + if (BLI_gset_add(menu_tagged, mt)) { + BLI_linklist_prepend(&menu_stack, mt); + } + } } } - } #undef SPACE_MENU_MAP #undef SPACE_MENU_NOP - bool has_keymap_menu_items = false; + bool has_keymap_menu_items = false; - GHashIterator iter; + while (menu_stack != NULL) { + MenuType *mt = BLI_linklist_pop(&menu_stack); + if (!WM_menutype_poll(C, mt)) { + continue; + } - while (menu_stack != NULL) { - MenuType *mt = BLI_linklist_pop(&menu_stack); - if (!WM_menutype_poll(C, mt)) { - continue; - } + uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS); + uiLayout *layout = UI_block_layout( + block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - uiBlock *block = UI_block_begin(C, region, __func__, UI_EMBOSS); - uiLayout *layout = UI_block_layout( - block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + UI_block_flag_enable(block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); - UI_block_flag_enable(block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); + uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN); + UI_menutype_draw(C, mt, layout); - uiLayoutSetOperatorContext(layout, WM_OP_INVOKE_REGION_WIN); - UI_menutype_draw(C, mt, layout); + UI_block_end(C, block); - UI_block_end(C, block); + LISTBASE_FOREACH (uiBut *, but, &block->buttons) { + MenuType *mt_from_but = NULL; + /* Support menu titles with dynamic from initial labels + * (used by edit-mesh context menu). */ + if (but->type == UI_BTYPE_LABEL) { - LISTBASE_FOREACH (uiBut *, but, &block->buttons) { - MenuType *mt_from_but = NULL; - /* Support menu titles with dynamic from initial labels - * (used by edit-mesh context menu). */ - if (but->type == UI_BTYPE_LABEL) { + /* Check if the label is the title. */ + uiBut *but_test = but->prev; + while (but_test && but_test->type == UI_BTYPE_SEPR) { + but_test = but_test->prev; + } - /* Check if the label is the title. */ - uiBut *but_test = but->prev; - while (but_test && but_test->type == UI_BTYPE_SEPR) { - but_test = but_test->prev; + if (but_test == NULL) { + BLI_ghash_insert( + menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr)); + } } - - if (but_test == NULL) { - BLI_ghash_insert( - menu_display_name_map, mt, (void *)strdup_memarena(memarena, but->drawstr)); + else if (menu_items_from_ui_create_item_from_button( + data, memarena, mt, NULL, but, wm_context)) { + /* pass */ } - } - else if (menu_items_from_ui_create_item_from_button(data, memarena, mt, NULL, but)) { - /* pass */ - } - else if ((mt_from_but = UI_but_menutype_get(but))) { + else if ((mt_from_but = UI_but_menutype_get(but))) { - if (BLI_gset_add(menu_tagged, mt_from_but)) { - BLI_linklist_prepend(&menu_stack, mt_from_but); - } + if (BLI_gset_add(menu_tagged, mt_from_but)) { + BLI_linklist_prepend(&menu_stack, mt_from_but); + } - if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) { - struct MenuSearch_Parent *menu_parent = BLI_memarena_calloc(memarena, - sizeof(*menu_parent)); - /* Use brackets for menu key shortcuts, - * converting "Text|Some-Shortcut" to "Text (Some-Shortcut)". - * This is needed so we don't right align sub-menu contents - * we only want to do that for the last menu item, not the path that leads to it. - */ - const char *drawstr_sep = but->flag & UI_BUT_HAS_SEP_CHAR ? - strrchr(but->drawstr, UI_SEP_CHAR) : - NULL; - bool drawstr_is_empty = false; - if (drawstr_sep != NULL) { - BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); - /* Detect empty string, fallback to menu name. */ - const char *drawstr = but->drawstr; - int drawstr_len = drawstr_sep - but->drawstr; - if (UNLIKELY(drawstr_len == 0)) { - drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); - drawstr_len = strlen(drawstr); - if (drawstr[0] == '\0') { - drawstr_is_empty = true; + if (!BLI_ghash_haskey(menu_parent_map, mt_from_but)) { + struct MenuSearch_Parent *menu_parent = BLI_memarena_calloc(memarena, + sizeof(*menu_parent)); + /* Use brackets for menu key shortcuts, + * converting "Text|Some-Shortcut" to "Text (Some-Shortcut)". + * This is needed so we don't right align sub-menu contents + * we only want to do that for the last menu item, not the path that leads to it. + */ + const char *drawstr_sep = but->flag & UI_BUT_HAS_SEP_CHAR ? + strrchr(but->drawstr, UI_SEP_CHAR) : + NULL; + bool drawstr_is_empty = false; + if (drawstr_sep != NULL) { + BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); + /* Detect empty string, fallback to menu name. */ + const char *drawstr = but->drawstr; + int drawstr_len = drawstr_sep - but->drawstr; + if (UNLIKELY(drawstr_len == 0)) { + drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); + drawstr_len = strlen(drawstr); + if (drawstr[0] == '\0') { + drawstr_is_empty = true; + } } + BLI_dynstr_nappend(dyn_str, drawstr, drawstr_len); + BLI_dynstr_appendf(dyn_str, " (%s)", drawstr_sep + 1); + menu_parent->drawstr = strdup_memarena_from_dynstr(memarena, dyn_str); + BLI_dynstr_clear(dyn_str); } - BLI_dynstr_nappend(dyn_str, drawstr, drawstr_len); - BLI_dynstr_appendf(dyn_str, " (%s)", drawstr_sep + 1); - menu_parent->drawstr = strdup_memarena_from_dynstr(memarena, dyn_str); - BLI_dynstr_clear(dyn_str); - } - else { - const char *drawstr = but->drawstr; - if (UNLIKELY(drawstr[0] == '\0')) { - drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); - if (drawstr[0] == '\0') { - drawstr_is_empty = true; + else { + const char *drawstr = but->drawstr; + if (UNLIKELY(drawstr[0] == '\0')) { + drawstr = CTX_IFACE_(mt_from_but->translation_context, mt_from_but->label); + if (drawstr[0] == '\0') { + drawstr_is_empty = true; + } } + menu_parent->drawstr = strdup_memarena(memarena, drawstr); } - menu_parent->drawstr = strdup_memarena(memarena, drawstr); - } - menu_parent->parent_mt = mt; - BLI_ghash_insert(menu_parent_map, mt_from_but, menu_parent); + menu_parent->parent_mt = mt; + BLI_ghash_insert(menu_parent_map, mt_from_but, menu_parent); - if (drawstr_is_empty) { - printf("Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->idname); + if (drawstr_is_empty) { + printf("Warning: '%s' menu has empty 'bl_label'.\n", mt_from_but->idname); + } } } - } - else if (but->menu_create_func != NULL) { - /* A non 'MenuType' menu button. */ + else if (but->menu_create_func != NULL) { + /* A non 'MenuType' menu button. */ - /* Only expand one level deep, this is mainly for expanding operator menus. */ - const char *drawstr_submenu = but->drawstr; + /* Only expand one level deep, this is mainly for expanding operator menus. */ + const char *drawstr_submenu = but->drawstr; - /* +1 to avoid overlap with the current 'block'. */ - uiBlock *sub_block = UI_block_begin(C, region, __func__ + 1, UI_EMBOSS); - uiLayout *sub_layout = UI_block_layout( - sub_block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); + /* +1 to avoid overlap with the current 'block'. */ + uiBlock *sub_block = UI_block_begin(C, region, __func__ + 1, UI_EMBOSS); + uiLayout *sub_layout = UI_block_layout( + sub_block, UI_LAYOUT_VERTICAL, UI_LAYOUT_MENU, 0, 0, 200, 0, UI_MENU_PADDING, style); - UI_block_flag_enable(sub_block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); + UI_block_flag_enable(sub_block, UI_BLOCK_SHOW_SHORTCUT_ALWAYS); - uiLayoutSetOperatorContext(sub_layout, WM_OP_INVOKE_REGION_WIN); + uiLayoutSetOperatorContext(sub_layout, WM_OP_INVOKE_REGION_WIN); - but->menu_create_func(C, sub_layout, but->poin); + but->menu_create_func(C, sub_layout, but->poin); - UI_block_end(C, sub_block); + UI_block_end(C, sub_block); - LISTBASE_FOREACH (uiBut *, sub_but, &sub_block->buttons) { - menu_items_from_ui_create_item_from_button(data, memarena, mt, drawstr_submenu, sub_but); - } + LISTBASE_FOREACH (uiBut *, sub_but, &sub_block->buttons) { + menu_items_from_ui_create_item_from_button( + data, memarena, mt, drawstr_submenu, sub_but, wm_context); + } - if (region) { - BLI_remlink(®ion->uiblocks, sub_block); + if (region) { + BLI_remlink(®ion->uiblocks, sub_block); + } + UI_block_free(NULL, sub_block); } - UI_block_free(NULL, sub_block); } - } - if (region) { - BLI_remlink(®ion->uiblocks, block); - } - UI_block_free(NULL, block); - - /* Add key-map items as a second pass, - * so all menus are accessed from the header & top-bar before key shortcuts are expanded. */ - if ((menu_stack == NULL) && (has_keymap_menu_items == false)) { - has_keymap_menu_items = true; - menu_types_add_from_keymap_items( - C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged); + if (region) { + BLI_remlink(®ion->uiblocks, block); + } + UI_block_free(NULL, block); + + /* Add key-map items as a second pass, + * so all menus are accessed from the header & top-bar before key shortcuts are expanded. */ + if ((menu_stack == NULL) && (has_keymap_menu_items == false)) { + has_keymap_menu_items = true; + menu_types_add_from_keymap_items( + C, win, area, region, &menu_stack, menu_to_kmi, menu_tagged); + } } } @@ -552,6 +667,17 @@ static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C, /* Set names as full paths. */ LISTBASE_FOREACH (struct MenuSearch_Item *, item, &data->items) { + BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); + + if (include_all_areas) { + BLI_dynstr_appendf( + dyn_str, + "%s: ", + (item->wm_context != NULL) ? + space_type_ui_items[item->wm_context->space_type_ui_index].name : + CTX_IFACE_(RNA_property_translation_context(prop_ui_type), "Top Bar")); + } + if (item->menu_parent != NULL) { struct MenuSearch_Parent *menu_parent = item->menu_parent; menu_parent->temp_child = NULL; @@ -559,7 +685,6 @@ static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C, menu_parent->parent->temp_child = menu_parent; menu_parent = menu_parent->parent; } - BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); while (menu_parent) { BLI_dynstr_append(dyn_str, menu_parent->drawstr); BLI_dynstr_append(dyn_str, " " MENU_SEP " "); @@ -567,7 +692,6 @@ static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C, } } else { - BLI_assert(BLI_dynstr_get_len(dyn_str) == 0); const char *drawstr = BLI_ghash_lookup(menu_display_name_map, item->mt); if (drawstr == NULL) { drawstr = CTX_IFACE_(item->mt->translation_context, item->mt->label); @@ -611,6 +735,15 @@ static struct MenuSearch_Data *menu_items_from_ui_create(bContext *C, data->memarena = memarena; + if (include_all_areas) { + CTX_wm_area_set(C, area_init); + CTX_wm_region_set(C, region_init); + + if (space_type_ui_items_free) { + MEM_freeN((void *)space_type_ui_items); + } + } + if (U.flag & USER_DEVELOPER_UI) { menu_items_from_all_operators(C, data); } @@ -650,6 +783,14 @@ static void menu_call_fn(bContext *C, void *UNUSED(arg1), void *arg2) return; } + ScrArea *area_prev = CTX_wm_area(C); + ARegion *region_prev = CTX_wm_region(C); + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, item->wm_context->area); + CTX_wm_region_set(C, item->wm_context->region); + } + switch (item->type) { case MENU_SEARCH_TYPE_OP: { CTX_store_set(C, item->op.context); @@ -687,6 +828,11 @@ static void menu_call_fn(bContext *C, void *UNUSED(arg1), void *arg2) break; } } + + if (item->wm_context != NULL) { + CTX_wm_area_set(C, area_prev); + CTX_wm_region_set(C, region_prev); + } } static void menu_search_cb(const bContext *UNUSED(C), @@ -731,7 +877,10 @@ void UI_but_func_menu_search(uiBut *but) wmWindow *win = CTX_wm_window(C); ScrArea *area = CTX_wm_area(C); ARegion *region = CTX_wm_region(C); - struct MenuSearch_Data *data = menu_items_from_ui_create(C, win, area, region); + /* When run from top-bar scan all areas in the current window. */ + bool include_all_areas = (area && (area->spacetype == SPACE_TOPBAR)); + struct MenuSearch_Data *data = menu_items_from_ui_create( + C, win, area, region, include_all_areas); UI_but_func_search_set(but, ui_searchbox_create_menu, menu_search_cb, |