*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);
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:
* <item label="">
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);
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
* 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;
fill_item("to.action", workspace->name);
}
- menu_update_scene(menu);
+ menu_create_scene(menu);
}
static void
* 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;
fill_item("to.action", workspace->name);
}
buf_reset(&buffer);
- menu_update_scene(menu);
+ menu_create_scene(menu);
}
static void
init_windowmenu(server);
init_client_list_combined_menu(server);
init_client_send_to_menu(server);
- post_processing(server);
validate(server);
}
_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)
{
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,
ctx->top_level_menu->id);
}
menu_level--;
- post_processing(ctx->server);
validate(ctx->server);
- menu_update_scene(current_menu);
return;
}
* 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);
/* 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;