Pipemenu, fix so both inline and stand alone work

This commit is contained in:
Droc 2024-07-19 17:18:31 -05:00
parent 3be8fe25f3
commit 1419c2bbc2
4 changed files with 114 additions and 51 deletions

View file

@ -27,6 +27,12 @@ struct menu_scene {
struct scaled_font_buffer *buffer; struct scaled_font_buffer *buffer;
}; };
enum menuitem_type {
LAB_MENU_ITEM = 0,
LAB_MENU_SEPARATOR_LINE,
LAB_MENU_TITLE,
};
struct menuitem { struct menuitem {
struct wl_list actions; struct wl_list actions;
char *execute; char *execute;
@ -34,6 +40,7 @@ struct menuitem {
struct menu *parent; struct menu *parent;
struct menu *submenu; struct menu *submenu;
bool selectable; bool selectable;
enum menuitem_type type;
int height; int height;
int native_width; int native_width;
struct wlr_scene_tree *tree; struct wlr_scene_tree *tree;

View file

@ -72,6 +72,8 @@ struct theme {
int menu_separator_padding_height; int menu_separator_padding_height;
float menu_separator_color[4]; float menu_separator_color[4];
float menu_title_bg_color[4];
int osd_border_width; int osd_border_width;
float osd_bg_color[4]; float osd_bg_color[4];

View file

@ -114,17 +114,27 @@ menu_update_width(struct menu *menu)
wlr_scene_rect_from_node(item->normal.background), wlr_scene_rect_from_node(item->normal.background),
menu->size.width, item->height); menu->size.width, item->height);
if (!item->selected.background) { /*
/* This is a separator. They don't have a selected background. */ * Separator lines are special because they change width with
* the menu.
*/
if (item->type == LAB_MENU_SEPARATOR_LINE) {
int width = menu->size.width
- 2 * theme->menu_separator_padding_width
- 2 * theme->menu_item_padding_x;
wlr_scene_rect_set_size( wlr_scene_rect_set_size(
wlr_scene_rect_from_node(item->normal.text), wlr_scene_rect_from_node(item->normal.text),
menu->size.width - 2 * theme->menu_separator_padding_width, width, theme->menu_separator_line_thickness);
theme->menu_separator_line_thickness); }
} else {
/* Usual menu item */ if (!item->selected.background) {
continue;
}
wlr_scene_rect_set_size( wlr_scene_rect_set_size(
wlr_scene_rect_from_node(item->selected.background), wlr_scene_rect_from_node(item->selected.background),
menu->size.width, item->height); menu->size.width, item->height);
if (item->native_width > max_width || item->submenu || item->execute) { if (item->native_width > max_width || item->submenu || item->execute) {
scaled_font_buffer_set_max_width(item->normal.buffer, scaled_font_buffer_set_max_width(item->normal.buffer,
max_width); max_width);
@ -133,7 +143,6 @@ menu_update_width(struct menu *menu)
} }
} }
} }
}
static void static void
post_processing(struct server *server) post_processing(struct server *server)
@ -178,11 +187,13 @@ item_create(struct menu *menu, const char *text, bool show_arrow)
struct menuitem *menuitem = znew(*menuitem); struct menuitem *menuitem = znew(*menuitem);
menuitem->parent = menu; menuitem->parent = menu;
menuitem->selectable = true; menuitem->selectable = true;
menuitem->type = LAB_MENU_ITEM;
struct server *server = menu->server; struct server *server = menu->server;
struct theme *theme = server->theme; struct theme *theme = server->theme;
const char *arrow = show_arrow ? "" : NULL; const char *arrow = show_arrow ? "" : NULL;
/* TODO: Consider setting this somewhere else */
if (!menu->item_height) { if (!menu->item_height) {
menu->item_height = font_height(&rc.font_menuitem) menu->item_height = font_height(&rc.font_menuitem)
+ 2 * theme->menu_item_padding_y; + 2 * theme->menu_item_padding_y;
@ -265,33 +276,69 @@ separator_create(struct menu *menu, const char *label)
struct menuitem *menuitem = znew(*menuitem); struct menuitem *menuitem = znew(*menuitem);
menuitem->parent = menu; menuitem->parent = menu;
menuitem->selectable = false; menuitem->selectable = false;
menuitem->type = label ? LAB_MENU_TITLE : LAB_MENU_SEPARATOR_LINE;
struct server *server = menu->server; struct server *server = menu->server;
struct theme *theme = server->theme; struct theme *theme = server->theme;
if (!menu->item_height) {
menu->item_height = font_height(&rc.font_menuitem)
+ 2 * theme->menu_item_padding_y;
}
if (menuitem->type == LAB_MENU_TITLE) {
menuitem->height = menu->item_height;
menuitem->native_width = font_width(&rc.font_menuitem, label);
} else if (menuitem->type == LAB_MENU_SEPARATOR_LINE){
menuitem->height = theme->menu_separator_line_thickness + menuitem->height = theme->menu_separator_line_thickness +
2 * theme->menu_separator_padding_height; 2 * theme->menu_separator_padding_height;
}
/* Menu item root node */
menuitem->tree = wlr_scene_tree_create(menu->scene_tree); menuitem->tree = wlr_scene_tree_create(menu->scene_tree);
node_descriptor_create(&menuitem->tree->node, node_descriptor_create(&menuitem->tree->node,
LAB_NODE_DESC_MENUITEM, menuitem); LAB_NODE_DESC_MENUITEM, menuitem);
/* Tree to hold background and text/line buffer */
menuitem->normal.tree = wlr_scene_tree_create(menuitem->tree); menuitem->normal.tree = wlr_scene_tree_create(menuitem->tree);
/* Item background nodes */
float *bg_color = label ? theme->menu_title_bg_color : theme->menu_items_bg_color;
menuitem->normal.background = &wlr_scene_rect_create( menuitem->normal.background = &wlr_scene_rect_create(
menuitem->normal.tree, menuitem->normal.tree,
menu->size.width, menuitem->height, menu->size.width, menuitem->height, bg_color)->node;
theme->menu_items_bg_color)->node;
int width = menu->size.width - 2 * theme->menu_separator_padding_width; /* Draw separator line or title */
if (menuitem->type == LAB_MENU_TITLE) {
menuitem->normal.buffer = scaled_font_buffer_create(menuitem->normal.tree);
if (!menuitem->normal.buffer) {
wlr_log(WLR_ERROR, "Failed to create menu item '%s'", label);
wlr_scene_node_destroy(&menuitem->tree->node);
free(menuitem);
return NULL;
}
menuitem->normal.text = &menuitem->normal.buffer->scene_buffer->node;
/* Font buffer */
scaled_font_buffer_update(menuitem->normal.buffer, label,
menuitem->native_width, &rc.font_menuitem,
theme->menu_items_text_color, bg_color, /* arrow */ NULL);
/* Center font nodes */
int x, y;
x = theme->menu_item_padding_x;
y = (menu->item_height - menuitem->normal.buffer->height) / 2;
wlr_scene_node_set_position(menuitem->normal.text, x, y);
} else {
int nominal_width = theme->menu_min_width;
menuitem->normal.text = &wlr_scene_rect_create( menuitem->normal.text = &wlr_scene_rect_create(
menuitem->normal.tree, menuitem->normal.tree, nominal_width,
width > 0 ? width : 0,
theme->menu_separator_line_thickness, theme->menu_separator_line_thickness,
theme->menu_separator_color)->node; theme->menu_separator_color)->node;
wlr_scene_node_set_position(&menuitem->tree->node, 0, menu->size.height); wlr_scene_node_set_position(&menuitem->tree->node, 0, menu->size.height);
/* Vertically center-align separator line */ /* Vertically center-align separator line */
wlr_scene_node_set_position(menuitem->normal.text, wlr_scene_node_set_position(menuitem->normal.text,
theme->menu_separator_padding_width, theme->menu_separator_padding_width
+ theme->menu_item_padding_x,
theme->menu_separator_padding_height); theme->menu_separator_padding_height);
}
wlr_scene_node_set_position(&menuitem->tree->node, 0, menu->size.height);
menu->size.height += menuitem->height; menu->size.height += menuitem->height;
wl_list_append(&menu->menuitems, &menuitem->link); wl_list_append(&menu->menuitems, &menuitem->link);
@ -507,26 +554,18 @@ handle_menu_element(xmlNode *n, struct server *server)
if (execute && label && id) { if (execute && label && id) {
wlr_log(WLR_DEBUG, "pipemenu '%s:%s:%s'", id, label, execute); wlr_log(WLR_DEBUG, "pipemenu '%s:%s:%s'", id, label, execute);
if (!current_menu) { if (!current_menu) {
/* current_menu = menu_create(server, id, label);
* We currently do not support pipemenus without a current_menu->is_pipemenu = true;
* parent <item> such as the one the example below:
*
* <?xml version="1.0" encoding="UTF-8"?>
* <openbox_menu>
* <menu id="root-menu" label="foo" execute="bar"/>
* </openbox_menu>
*
* TODO: Consider supporting this
*/
wlr_log(WLR_ERROR,
"pipemenu '%s:%s:%s' has no parent <menu>",
id, label, execute);
goto error;
}
current_item = item_create(current_menu, label, /* arrow */ true); current_item = item_create(current_menu, label, /* arrow */ true);
current_item_action = NULL; current_item_action = NULL;
current_item->execute = xstrdup(execute); current_item->execute = xstrdup(execute);
current_item->id = xstrdup(id); current_item->id = xstrdup(id);
} else {
current_item = item_create(current_menu, label, /* arrow */ true);
current_item_action = NULL;
current_item->execute = xstrdup(execute);
current_item->id = xstrdup(id);
}
} else if ((label && id) || is_toplevel_static_menu_definition(n, id)) { } else if ((label && id) || is_toplevel_static_menu_definition(n, id)) {
/* /*
* (label && id) refers to <menu id="" label=""> which is an * (label && id) refers to <menu id="" label=""> which is an
@ -582,7 +621,16 @@ handle_menu_element(xmlNode *n, struct server *server)
} }
struct menu *menu = menu_get_by_id(server, id); struct menu *menu = menu_get_by_id(server, id);
if (menu) { if (menu && menu->is_pipemenu) {
current_item = item_create(current_menu, menu->label, true);
struct menuitem *item;
wl_list_for_each(item, &menu->menuitems, link) {
current_item->execute = xstrdup(item->execute);
char buffer[256];
sprintf(buffer, "%s%d", item->id, rand());
current_item->id = xstrdup(buffer);
}
} else if (menu) {
current_item = item_create(current_menu, menu->label, true); current_item = item_create(current_menu, menu->label, true);
if (current_item) { if (current_item) {
current_item->submenu = menu; current_item->submenu = menu;

View file

@ -526,6 +526,8 @@ theme_builtin(struct theme *theme, struct server *server)
theme->menu_separator_padding_height = 3; theme->menu_separator_padding_height = 3;
parse_hexstr("#888888", theme->menu_separator_color); parse_hexstr("#888888", theme->menu_separator_color);
parse_hexstr("#589bda", theme->menu_title_bg_color);
theme->osd_window_switcher_width = 600; theme->osd_window_switcher_width = 600;
theme->osd_window_switcher_width_is_percent = false; theme->osd_window_switcher_width_is_percent = false;
theme->osd_window_switcher_padding = 4; theme->osd_window_switcher_padding = 4;
@ -755,6 +757,10 @@ entry(struct theme *theme, const char *key, const char *value)
parse_hexstr(value, theme->menu_separator_color); parse_hexstr(value, theme->menu_separator_color);
} }
if (match_glob(key, "menu.title.bg.color")) {
parse_hexstr(value, theme->menu_title_bg_color);
}
if (match_glob(key, "osd.bg.color")) { if (match_glob(key, "osd.bg.color")) {
parse_hexstr(value, theme->osd_bg_color); parse_hexstr(value, theme->osd_bg_color);
} }