mirror of
https://github.com/labwc/labwc.git
synced 2026-03-03 01:40:37 -05:00
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:
<menu id="foo" label="foo">
<item label="aaaaaa"/>
<item label="bbbbbb"/>
</menu>
<menu id="root-menu">
<menu id="foo" />
<menu id="foo" />
</menu>
This commit is contained in:
parent
514f1d4fc4
commit
12f95543f0
3 changed files with 50 additions and 85 deletions
|
|
@ -127,7 +127,4 @@ void menu_close_root(struct server *server);
|
||||||
/* menu_reconfigure - reload theme and content */
|
/* menu_reconfigure - reload theme and content */
|
||||||
void menu_reconfigure(struct server *server);
|
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 */
|
#endif /* LABWC_MENU_H */
|
||||||
|
|
|
||||||
10
src/action.c
10
src/action.c
|
|
@ -664,16 +664,6 @@ show_menu(struct server *server, struct view *view, struct cursor_context *ctx,
|
||||||
return;
|
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 x = server->seat.cursor->x;
|
||||||
int y = server->seat.cursor->y;
|
int y = server->seat.cursor->y;
|
||||||
|
|
||||||
|
|
|
||||||
122
src/menu/menu.c
122
src/menu/menu.c
|
|
@ -362,19 +362,30 @@ title_create_scene(struct menuitem *menuitem, int *item_y)
|
||||||
*item_y += theme->menu_header_height;
|
*item_y += theme->menu_header_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (Re)creates the scene of the menu */
|
static void item_destroy(struct menuitem *item);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
menu_update_scene(struct menu *menu)
|
reset_menu(struct menu *menu)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
menu->scene_tree = NULL;
|
||||||
|
}
|
||||||
|
/* TODO: also reset other fields? */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
menu_create_scene(struct menu *menu)
|
||||||
{
|
{
|
||||||
struct menuitem *item;
|
struct menuitem *item;
|
||||||
struct theme *theme = menu->server->theme;
|
struct theme *theme = menu->server->theme;
|
||||||
|
|
||||||
if (menu->scene_tree) {
|
assert(!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 = wlr_scene_tree_create(menu->server->menu_tree);
|
menu->scene_tree = wlr_scene_tree_create(menu->server->menu_tree);
|
||||||
wlr_scene_node_set_enabled(&menu->scene_tree->node, false);
|
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);
|
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:
|
* Handle the following:
|
||||||
* <item label="">
|
* <item label="">
|
||||||
|
|
@ -916,8 +911,6 @@ get_item_anchor_rect(struct theme *theme, struct menuitem *item)
|
||||||
static void
|
static void
|
||||||
menu_reposition(struct menu *menu, struct wlr_box anchor_rect)
|
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 */
|
/* Get output usable area to place the menu within */
|
||||||
struct output *output = output_nearest_to(menu->server,
|
struct output *output = output_nearest_to(menu->server,
|
||||||
anchor_rect.x, anchor_rect.y);
|
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);
|
wlr_scene_node_set_position(&menu->scene_tree->node, box.x, box.y);
|
||||||
|
|
||||||
menu->align_left = (box.x < anchor_rect.x);
|
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
|
static void
|
||||||
|
|
@ -1006,20 +990,13 @@ init_client_send_to_menu(struct server *server)
|
||||||
* with the workspace names that can be used with
|
* with the workspace names that can be used with
|
||||||
* SendToDesktop, left/right options are included.
|
* SendToDesktop, left/right options are included.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
update_client_send_to_menu(struct server *server)
|
update_client_send_to_menu(struct server *server)
|
||||||
{
|
{
|
||||||
struct menu *menu = menu_get_by_id(server,
|
struct menu *menu = menu_get_by_id(server, "client-send-to-menu");
|
||||||
"client-send-to-menu");
|
assert(menu);
|
||||||
|
|
||||||
if (menu) {
|
reset_menu(menu);
|
||||||
struct menuitem *item, *next;
|
|
||||||
wl_list_for_each_safe(item, next, &menu->menuitems, link) {
|
|
||||||
item_destroy(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
menu->size.height = 0;
|
|
||||||
|
|
||||||
struct workspace *workspace;
|
struct workspace *workspace;
|
||||||
|
|
||||||
|
|
@ -1036,7 +1013,7 @@ update_client_send_to_menu(struct server *server)
|
||||||
fill_item("to.action", workspace->name);
|
fill_item("to.action", workspace->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_update_scene(menu);
|
menu_create_scene(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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
|
* separator label and the titles of the view, if any, below each workspace
|
||||||
* name. Active view is indicated by "*" preceding title.
|
* name. Active view is indicated by "*" preceding title.
|
||||||
*/
|
*/
|
||||||
void
|
static void
|
||||||
update_client_list_combined_menu(struct server *server)
|
update_client_list_combined_menu(struct server *server)
|
||||||
{
|
{
|
||||||
struct menu *menu = menu_get_by_id(server, "client-list-combined-menu");
|
struct menu *menu = menu_get_by_id(server, "client-list-combined-menu");
|
||||||
|
assert(menu);
|
||||||
|
|
||||||
if (!menu) {
|
reset_menu(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;
|
|
||||||
|
|
||||||
struct workspace *workspace;
|
struct workspace *workspace;
|
||||||
struct view *view;
|
struct view *view;
|
||||||
|
|
@ -1108,7 +1075,7 @@ update_client_list_combined_menu(struct server *server)
|
||||||
fill_item("to.action", workspace->name);
|
fill_item("to.action", workspace->name);
|
||||||
}
|
}
|
||||||
buf_reset(&buffer);
|
buf_reset(&buffer);
|
||||||
menu_update_scene(menu);
|
menu_create_scene(menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
@ -1191,7 +1158,6 @@ menu_init(struct server *server)
|
||||||
init_windowmenu(server);
|
init_windowmenu(server);
|
||||||
init_client_list_combined_menu(server);
|
init_client_list_combined_menu(server);
|
||||||
init_client_send_to_menu(server);
|
init_client_send_to_menu(server);
|
||||||
post_processing(server);
|
|
||||||
validate(server);
|
validate(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1358,6 +1324,23 @@ menu_close(struct menu *menu)
|
||||||
_close(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
|
void
|
||||||
menu_open_root(struct menu *menu, int x, int y)
|
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);
|
assert(!menu->server->menu_current);
|
||||||
|
|
||||||
menu_reposition(menu, (struct wlr_box){.x = x, .y = y});
|
open_menu(menu, (struct wlr_box){.x = x, .y = y});
|
||||||
wlr_scene_node_set_enabled(&menu->scene_tree->node, true);
|
|
||||||
menu->server->menu_current = menu;
|
menu->server->menu_current = menu;
|
||||||
selected_item = NULL;
|
selected_item = NULL;
|
||||||
seat_focus_override_begin(&menu->server->seat,
|
seat_focus_override_begin(&menu->server->seat,
|
||||||
|
|
@ -1402,9 +1384,7 @@ create_pipe_menu(struct menu_pipe_context *ctx)
|
||||||
ctx->top_level_menu->id);
|
ctx->top_level_menu->id);
|
||||||
}
|
}
|
||||||
menu_level--;
|
menu_level--;
|
||||||
post_processing(ctx->server);
|
|
||||||
validate(ctx->server);
|
validate(ctx->server);
|
||||||
menu_update_scene(current_menu);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1445,12 +1425,9 @@ create_pipe_menu(struct menu_pipe_context *ctx)
|
||||||
* operate from current point onwards
|
* operate from current point onwards
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Set menu-widths before configuring */
|
|
||||||
post_processing(ctx->server);
|
|
||||||
|
|
||||||
struct wlr_box anchor_rect =
|
struct wlr_box anchor_rect =
|
||||||
get_item_anchor_rect(ctx->server->theme, ctx->item);
|
get_item_anchor_rect(ctx->server->theme, ctx->item);
|
||||||
menu_reposition(pipe_menu, anchor_rect);
|
open_menu(pipe_menu, anchor_rect);
|
||||||
|
|
||||||
validate(ctx->server);
|
validate(ctx->server);
|
||||||
|
|
||||||
|
|
@ -1625,8 +1602,9 @@ menu_process_item_selection(struct menuitem *item)
|
||||||
/* Ensure the submenu has its parent set correctly */
|
/* Ensure the submenu has its parent set correctly */
|
||||||
item->submenu->parent = item->parent;
|
item->submenu->parent = item->parent;
|
||||||
/* And open the new submenu tree */
|
/* And open the new submenu tree */
|
||||||
wlr_scene_node_set_enabled(
|
struct wlr_box anchor_rect =
|
||||||
&item->submenu->scene_tree->node, true);
|
get_item_anchor_rect(item->submenu->server->theme, item);
|
||||||
|
open_menu(item->submenu, anchor_rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
item->parent->selection.menu = item->submenu;
|
item->parent->selection.menu = item->submenu;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue