From: tokyo4j Date: Sun, 9 Mar 2025 15:00:39 +0000 (+0900) Subject: menu: lazily generate menu scenes X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=12f95543f0796eae12cc2be56f76b69b89fe5dea;p=proto%2Flabwc.git menu: lazily generate menu scenes This removes the need to call update_client_list_combined_menu() and update_client_send_to_menu() every time a root menu is opened. This commit also fixed the incorrect menu position with following configuration: --- diff --git a/include/menu/menu.h b/include/menu/menu.h index ef336d29..f69e902a 100644 --- a/include/menu/menu.h +++ b/include/menu/menu.h @@ -127,7 +127,4 @@ void menu_close_root(struct server *server); /* menu_reconfigure - reload theme and content */ void menu_reconfigure(struct server *server); -void update_client_list_combined_menu(struct server *server); -void update_client_send_to_menu(struct server *server); - #endif /* LABWC_MENU_H */ diff --git a/src/action.c b/src/action.c index 6f99cc46..07b5c6a6 100644 --- a/src/action.c +++ b/src/action.c @@ -664,16 +664,6 @@ show_menu(struct server *server, struct view *view, struct cursor_context *ctx, return; } - /* - * We always refresh client-list-combined-menu and client-send-to-menu - * so that they are up-to-date whether they are directly opened as a - * top-level menu or opened as a submenu which we don't know at this - * point. It is also needed to calculate the proper width for placement - * as it fluctuates depending on application/workspace titles. - */ - update_client_list_combined_menu(menu->server); - update_client_send_to_menu(menu->server); - int x = server->seat.cursor->x; int y = server->seat.cursor->y; diff --git a/src/menu/menu.c b/src/menu/menu.c index 0605b1f6..ebf16419 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -362,19 +362,30 @@ title_create_scene(struct menuitem *menuitem, int *item_y) *item_y += theme->menu_header_height; } -/* (Re)creates the scene of the menu */ +static void item_destroy(struct menuitem *item); + static void -menu_update_scene(struct menu *menu) +reset_menu(struct menu *menu) { - struct menuitem *item; - struct theme *theme = menu->server->theme; - + struct menuitem *item, *next; + wl_list_for_each_safe(item, next, &menu->menuitems, link) { + item_destroy(item); + } if (menu->scene_tree) { wlr_scene_node_destroy(&menu->scene_tree->node); - wl_list_for_each(item, &menu->menuitems, link) { - item->tree = NULL; - } + menu->scene_tree = NULL; } + /* TODO: also reset other fields? */ +} + +static void +menu_create_scene(struct menu *menu) +{ + struct menuitem *item; + struct theme *theme = menu->server->theme; + + assert(!menu->scene_tree); + menu->scene_tree = wlr_scene_tree_create(menu->server->menu_tree); wlr_scene_node_set_enabled(&menu->scene_tree->node, false); @@ -420,22 +431,6 @@ menu_update_scene(struct menu *menu) wlr_scene_node_lower_to_bottom(&bg_buffer->scene_buffer->node); } -static void -post_processing(struct server *server) -{ - /* - * Create menu scene after all of its contents is determined - * (e.g. when finished reading menu.xml or received output from - * pipemenu program). - */ - struct menu *menu; - wl_list_for_each(menu, &server->menus, link) { - if (!menu->scene_tree) { - menu_update_scene(menu); - } - } -} - /* * Handle the following: * @@ -916,8 +911,6 @@ get_item_anchor_rect(struct theme *theme, struct menuitem *item) static void menu_reposition(struct menu *menu, struct wlr_box anchor_rect) { - struct theme *theme = menu->server->theme; - /* Get output usable area to place the menu within */ struct output *output = output_nearest_to(menu->server, anchor_rect.x, anchor_rect.y); @@ -962,15 +955,6 @@ menu_reposition(struct menu *menu, struct wlr_box anchor_rect) wlr_scene_node_set_position(&menu->scene_tree->node, box.x, box.y); menu->align_left = (box.x < anchor_rect.x); - - struct menuitem *item; - wl_list_for_each(item, &menu->menuitems, link) { - if (!item->submenu) { - continue; - } - anchor_rect = get_item_anchor_rect(theme, item); - menu_reposition(item->submenu, anchor_rect); - } } static void @@ -1006,20 +990,13 @@ init_client_send_to_menu(struct server *server) * with the workspace names that can be used with * SendToDesktop, left/right options are included. */ -void +static void update_client_send_to_menu(struct server *server) { - struct menu *menu = menu_get_by_id(server, - "client-send-to-menu"); - - if (menu) { - struct menuitem *item, *next; - wl_list_for_each_safe(item, next, &menu->menuitems, link) { - item_destroy(item); - } - } + struct menu *menu = menu_get_by_id(server, "client-send-to-menu"); + assert(menu); - menu->size.height = 0; + reset_menu(menu); struct workspace *workspace; @@ -1036,7 +1013,7 @@ update_client_send_to_menu(struct server *server) fill_item("to.action", workspace->name); } - menu_update_scene(menu); + menu_create_scene(menu); } static void @@ -1054,23 +1031,13 @@ init_client_list_combined_menu(struct server *server) * separator label and the titles of the view, if any, below each workspace * name. Active view is indicated by "*" preceding title. */ -void +static void update_client_list_combined_menu(struct server *server) { struct menu *menu = menu_get_by_id(server, "client-list-combined-menu"); + assert(menu); - if (!menu) { - /* Menu is created on compositor startup/reconfigure */ - wlr_log(WLR_ERROR, "client-list-combined-menu does not exist"); - return; - } - - struct menuitem *item, *next; - wl_list_for_each_safe(item, next, &menu->menuitems, link) { - item_destroy(item); - } - - menu->size.height = 0; + reset_menu(menu); struct workspace *workspace; struct view *view; @@ -1108,7 +1075,7 @@ update_client_list_combined_menu(struct server *server) fill_item("to.action", workspace->name); } buf_reset(&buffer); - menu_update_scene(menu); + menu_create_scene(menu); } static void @@ -1191,7 +1158,6 @@ menu_init(struct server *server) init_windowmenu(server); init_client_list_combined_menu(server); init_client_send_to_menu(server); - post_processing(server); validate(server); } @@ -1358,6 +1324,23 @@ menu_close(struct menu *menu) _close(menu); } +static void +open_menu(struct menu *menu, struct wlr_box anchor_rect) +{ + if (!strcmp(menu->id, "client-list-combined-menu")) { + update_client_list_combined_menu(menu->server); + } else if (!strcmp(menu->id, "client-send-to-menu")) { + update_client_send_to_menu(menu->server); + } + + if (!menu->scene_tree) { + menu_create_scene(menu); + assert(menu->scene_tree); + } + menu_reposition(menu, anchor_rect); + wlr_scene_node_set_enabled(&menu->scene_tree->node, true); +} + void menu_open_root(struct menu *menu, int x, int y) { @@ -1369,8 +1352,7 @@ menu_open_root(struct menu *menu, int x, int y) assert(!menu->server->menu_current); - menu_reposition(menu, (struct wlr_box){.x = x, .y = y}); - wlr_scene_node_set_enabled(&menu->scene_tree->node, true); + open_menu(menu, (struct wlr_box){.x = x, .y = y}); menu->server->menu_current = menu; selected_item = NULL; seat_focus_override_begin(&menu->server->seat, @@ -1402,9 +1384,7 @@ create_pipe_menu(struct menu_pipe_context *ctx) ctx->top_level_menu->id); } menu_level--; - post_processing(ctx->server); validate(ctx->server); - menu_update_scene(current_menu); return; } @@ -1445,12 +1425,9 @@ create_pipe_menu(struct menu_pipe_context *ctx) * operate from current point onwards */ - /* Set menu-widths before configuring */ - post_processing(ctx->server); - struct wlr_box anchor_rect = get_item_anchor_rect(ctx->server->theme, ctx->item); - menu_reposition(pipe_menu, anchor_rect); + open_menu(pipe_menu, anchor_rect); validate(ctx->server); @@ -1625,8 +1602,9 @@ menu_process_item_selection(struct menuitem *item) /* Ensure the submenu has its parent set correctly */ item->submenu->parent = item->parent; /* And open the new submenu tree */ - wlr_scene_node_set_enabled( - &item->submenu->scene_tree->node, true); + struct wlr_box anchor_rect = + get_item_anchor_rect(item->submenu->server->theme, item); + open_menu(item->submenu, anchor_rect); } item->parent->selection.menu = item->submenu;