diff --git a/include/menu/menu.h b/include/menu/menu.h index 2a28cd82..8f688c5c 100644 --- a/include/menu/menu.h +++ b/include/menu/menu.h @@ -25,6 +25,7 @@ struct menu { char *id; char *label; bool visible; + struct menu *parent; struct wlr_box box; struct wl_list menuitems; struct server *server; diff --git a/src/menu/menu.c b/src/menu/menu.c index 83b38524..5b3337fe 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -27,6 +27,7 @@ static bool in_item; static struct menuitem *current_item; +static int menu_level; static struct menu *current_menu; /* vector for elements */ @@ -46,6 +47,7 @@ menu_create(struct server *server, const char *id, const char *label) wl_list_init(&menu->menuitems); menu->id = strdup(id); menu->label = strdup(label); + menu->parent = current_menu; menu->server = server; return menu; } @@ -178,8 +180,23 @@ handle_menu_element(xmlNode *n, struct server *server) if (execute) { wlr_log(WLR_ERROR, "we do not support pipemenus"); } else if (label && id) { + struct menu **submenu = NULL; + if (menu_level > 0) { + /* + * In a nested (inline) menu definition we need to + * create an item pointing to the new submenu + */ + current_item = item_create(current_menu, label); + submenu = ¤t_item->submenu; + } + ++menu_level; current_menu = menu_create(server, id, label); - /* TODO: deal with nested menu definitions */ + if (submenu) { + *submenu = current_menu; + } + traverse(n, server); + current_menu = current_menu->parent; + --menu_level; } else if (id) { struct menu *menu = get_menu_by_id(id); if (menu) { @@ -203,7 +220,6 @@ xml_tree_walk(xmlNode *node, struct server *server) } if (!strcasecmp((char *)n->name, "menu")) { handle_menu_element(n, server); - traverse(n, server); continue; } if (!strcasecmp((char *)n->name, "item")) {