menu separator

changes to make separators work with/without label, added text color, font selection and center justification for label headers
This commit is contained in:
Droc 2024-08-17 08:47:14 -05:00
parent 8ce564551d
commit 6ff0d0a675
14 changed files with 95 additions and 9 deletions

View file

@ -448,6 +448,7 @@ extending outward from the snapped edge.
- ActiveWindow - titlebar of active window - ActiveWindow - titlebar of active window
- InactiveWindow - titlebar of all windows that aren't focused by the - InactiveWindow - titlebar of all windows that aren't focused by the
cursor cursor
- MenuHeader - menu header font ie separator labels
- MenuItem - menu item (currently only root menu) - MenuItem - menu item (currently only root menu)
- OnScreenDisplay - items in the on screen display - OnScreenDisplay - items in the on screen display
If no place attribute is provided, the setting will be applied to all If no place attribute is provided, the setting will be applied to all
@ -460,7 +461,7 @@ extending outward from the snapped edge.
Font size in pixels. Default is 10. Font size in pixels. Default is 10.
*<theme><font place=""><slant>* *<theme><font place=""><slant>*
Font slant (normal or italic). Default is normal. Font slant (normal, oblique or italic). Default is normal.
*<theme><font place=""><weight>* *<theme><font place=""><weight>*
Font weight (normal or bold). Default is normal. Font weight (normal or bold). Default is normal.

View file

@ -67,6 +67,10 @@ labwc-config(5).
Vertical padding of menu text entries in pixels. Vertical padding of menu text entries in pixels.
Default is 4. Default is 4.
*menu.title.text.justify*
Specifies how menu titles are aligned in the titlebar.
Type justification. Default Left.
*menu.overlap.x* *menu.overlap.x*
Horizontal overlap in pixels between submenus and their parents. A Horizontal overlap in pixels between submenus and their parents. A
positive value move submenus over the top of their parents, whereas a positive value move submenus over the top of their parents, whereas a
@ -178,6 +182,12 @@ elements are not listed here, but are supported.
Menu title color. Default #589bda. Menu title color. Default #589bda.
Note: A menu title is a separator with a label. Note: A menu title is a separator with a label.
*menu.title.bg.color*
Background color of separator label.
*menu.title.text.color*
Text color of separator label.
*osd.bg.color* *osd.bg.color*
Background color of on-screen-display. Inherits Background color of on-screen-display. Inherits
*window.active.title.bg.color* if not set. *window.active.title.bg.color* if not set.

View file

@ -61,6 +61,12 @@
</menu> </menu>
<menu id="some-custom-menu"> <menu id="some-custom-menu">
<!--
Creates a separator w/title that is used as a header
To create an empty header with no title,
set label=" ", not label=""
-->
<separator label="custom menu" />
<item label="Reconfigure"> <item label="Reconfigure">
<action name="Reconfigure" /> <action name="Reconfigure" />
</item> </item>

View file

@ -43,6 +43,12 @@
<slant>normal</slant> <slant>normal</slant>
<weight>normal</weight> <weight>normal</weight>
</font> </font>
<font place="MenuHeader">
<name>sans</name>
<size>10</size>
<slant>normal</slant>
<weight>normal</weight>
</font>
<font place="MenuItem"> <font place="MenuItem">
<name>sans</name> <name>sans</name>
<size>10</size> <size>10</size>

View file

@ -58,11 +58,13 @@ menu.items.active.bg.color: #e1dedb
menu.items.active.text.color: #000000 menu.items.active.text.color: #000000
menu.items.padding.x: 7 menu.items.padding.x: 7
menu.items.padding.y: 4 menu.items.padding.y: 4
menu.title.text.justify: left
menu.separator.width: 1 menu.separator.width: 1
menu.separator.padding.width: 6 menu.separator.padding.width: 6
menu.separator.padding.height: 3 menu.separator.padding.height: 3
menu.separator.color: #888888 menu.separator.color: #888888
menu.title.bg.color: #589bda menu.title.bg.color: #589bda
menu.title.text.color: #ffff00
# on screen display (window-cycle dialog) # on screen display (window-cycle dialog)
osd.bg.color: #e1dedb osd.bg.color: #e1dedb

View file

@ -6,7 +6,8 @@ struct lab_data_buffer;
enum font_slant { enum font_slant {
FONT_SLANT_NORMAL = 0, FONT_SLANT_NORMAL = 0,
FONT_SLANT_ITALIC FONT_SLANT_ITALIC,
FONT_SLANT_OBLIQUE
}; };
enum font_weight { enum font_weight {

View file

@ -86,6 +86,7 @@ struct rcxml {
bool shadows_enabled; bool shadows_enabled;
struct font font_activewindow; struct font font_activewindow;
struct font font_inactivewindow; struct font font_inactivewindow;
struct font font_menuheader;
struct font font_menuitem; struct font font_menuitem;
struct font font_osd; struct font font_osd;

View file

@ -135,4 +135,7 @@ 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 create_client_send_to_menu(struct server *server);
void create_client_list_combined_menu(struct server *server);
#endif /* LABWC_MENU_H */ #endif /* LABWC_MENU_H */

View file

@ -44,6 +44,7 @@ struct theme {
float window_active_label_text_color[4]; float window_active_label_text_color[4];
float window_inactive_label_text_color[4]; float window_inactive_label_text_color[4];
enum lab_justification window_label_text_justify; enum lab_justification window_label_text_justify;
enum lab_justification menu_title_text_justify;
/* button width */ /* button width */
int window_button_width; int window_button_width;
@ -77,6 +78,7 @@ struct theme {
float menu_separator_color[4]; float menu_separator_color[4];
float menu_title_bg_color[4]; float menu_title_bg_color[4];
float menu_title_text_color[4];
int osd_border_width; int osd_border_width;

View file

@ -630,6 +630,10 @@ show_menu(struct server *server, struct view *view,
return; return;
} }
/* need to be current to be useful */
create_client_list_combined_menu(menu->server);
create_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;
@ -655,11 +659,15 @@ show_menu(struct server *server, struct view *view,
y = rc.resize_popup_fixed_position.y + output_box.y; y = rc.resize_popup_fixed_position.y + output_box.y;
} else { /* Center the menu */ } else { /* Center the menu */
struct menuitem *item; struct menuitem *item;
int max_width = 0; struct theme *theme = server->theme;
int max_width = theme->menu_min_width;
wl_list_for_each(item, &menu->menuitems, link) { wl_list_for_each(item, &menu->menuitems, link) {
if (item->native_width > max_width) { if (item->native_width > max_width) {
max_width = item->native_width; max_width = item->native_width <
theme->menu_max_width ?
item->native_width :
theme->menu_max_width;
} }
} }
x = (output->usable_area.width / 2) - x = (output->usable_area.width / 2) -

View file

@ -20,6 +20,9 @@ font_to_pango_desc(struct font *font)
if (font->slant == FONT_SLANT_ITALIC) { if (font->slant == FONT_SLANT_ITALIC) {
pango_font_description_set_style(desc, PANGO_STYLE_ITALIC); pango_font_description_set_style(desc, PANGO_STYLE_ITALIC);
} }
if (font->slant == FONT_SLANT_OBLIQUE) {
pango_font_description_set_style(desc, PANGO_STYLE_OBLIQUE);
}
if (font->weight == FONT_WEIGHT_BOLD) { if (font->weight == FONT_WEIGHT_BOLD) {
pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
} }

View file

@ -69,6 +69,7 @@ enum font_place {
FONT_PLACE_UNKNOWN, FONT_PLACE_UNKNOWN,
FONT_PLACE_ACTIVEWINDOW, FONT_PLACE_ACTIVEWINDOW,
FONT_PLACE_INACTIVEWINDOW, FONT_PLACE_INACTIVEWINDOW,
FONT_PLACE_MENUHEADER,
FONT_PLACE_MENUITEM, FONT_PLACE_MENUITEM,
FONT_PLACE_OSD, FONT_PLACE_OSD,
/* TODO: Add all places based on Openbox's rc.xml */ /* TODO: Add all places based on Openbox's rc.xml */
@ -691,8 +692,13 @@ set_font_attr(struct font *font, const char *nodename, const char *content)
} else if (!strcmp(nodename, "size")) { } else if (!strcmp(nodename, "size")) {
font->size = atoi(content); font->size = atoi(content);
} else if (!strcmp(nodename, "slant")) { } else if (!strcmp(nodename, "slant")) {
font->slant = !strcasecmp(content, "italic") ? if (!strcasecmp(content, "italic")) {
FONT_SLANT_ITALIC : FONT_SLANT_NORMAL; font->slant = FONT_SLANT_ITALIC;
} else if (!strcasecmp(content, "oblique")) {
font->slant = FONT_SLANT_OBLIQUE;
} else {
font->slant = FONT_SLANT_NORMAL;
}
} else if (!strcmp(nodename, "weight")) { } else if (!strcmp(nodename, "weight")) {
font->weight = !strcasecmp(content, "bold") ? font->weight = !strcasecmp(content, "bold") ?
FONT_WEIGHT_BOLD : FONT_WEIGHT_NORMAL; FONT_WEIGHT_BOLD : FONT_WEIGHT_NORMAL;
@ -715,6 +721,7 @@ fill_font(char *nodename, char *content, enum font_place place)
*/ */
set_font_attr(&rc.font_activewindow, nodename, content); set_font_attr(&rc.font_activewindow, nodename, content);
set_font_attr(&rc.font_inactivewindow, nodename, content); set_font_attr(&rc.font_inactivewindow, nodename, content);
set_font_attr(&rc.font_menuheader, nodename, content);
set_font_attr(&rc.font_menuitem, nodename, content); set_font_attr(&rc.font_menuitem, nodename, content);
set_font_attr(&rc.font_osd, nodename, content); set_font_attr(&rc.font_osd, nodename, content);
break; break;
@ -724,6 +731,9 @@ fill_font(char *nodename, char *content, enum font_place place)
case FONT_PLACE_INACTIVEWINDOW: case FONT_PLACE_INACTIVEWINDOW:
set_font_attr(&rc.font_inactivewindow, nodename, content); set_font_attr(&rc.font_inactivewindow, nodename, content);
break; break;
case FONT_PLACE_MENUHEADER:
set_font_attr(&rc.font_menuheader, nodename, content);
break;
case FONT_PLACE_MENUITEM: case FONT_PLACE_MENUITEM:
set_font_attr(&rc.font_menuitem, nodename, content); set_font_attr(&rc.font_menuitem, nodename, content);
break; break;
@ -748,6 +758,8 @@ enum_font_place(const char *place)
return FONT_PLACE_ACTIVEWINDOW; return FONT_PLACE_ACTIVEWINDOW;
} else if (!strcasecmp(place, "InactiveWindow")) { } else if (!strcasecmp(place, "InactiveWindow")) {
return FONT_PLACE_INACTIVEWINDOW; return FONT_PLACE_INACTIVEWINDOW;
} else if (!strcasecmp(place, "MenuHeader")) {
return FONT_PLACE_MENUHEADER;
} else if (!strcasecmp(place, "MenuItem")) { } else if (!strcasecmp(place, "MenuItem")) {
return FONT_PLACE_MENUITEM; return FONT_PLACE_MENUITEM;
} else if (!strcasecmp(place, "OnScreenDisplay") } else if (!strcasecmp(place, "OnScreenDisplay")
@ -1277,6 +1289,7 @@ rcxml_init(void)
init_font_defaults(&rc.font_activewindow); init_font_defaults(&rc.font_activewindow);
init_font_defaults(&rc.font_inactivewindow); init_font_defaults(&rc.font_inactivewindow);
init_font_defaults(&rc.font_menuheader);
init_font_defaults(&rc.font_menuitem); init_font_defaults(&rc.font_menuitem);
init_font_defaults(&rc.font_osd); init_font_defaults(&rc.font_osd);
@ -1523,6 +1536,9 @@ post_processing(void)
if (!rc.font_inactivewindow.name) { if (!rc.font_inactivewindow.name) {
rc.font_inactivewindow.name = xstrdup("sans"); rc.font_inactivewindow.name = xstrdup("sans");
} }
if (!rc.font_menuheader.name) {
rc.font_menuheader.name = xstrdup("sans");
}
if (!rc.font_menuitem.name) { if (!rc.font_menuitem.name) {
rc.font_menuitem.name = xstrdup("sans"); rc.font_menuitem.name = xstrdup("sans");
} }
@ -1728,6 +1744,7 @@ rcxml_finish(void)
{ {
zfree(rc.font_activewindow.name); zfree(rc.font_activewindow.name);
zfree(rc.font_inactivewindow.name); zfree(rc.font_inactivewindow.name);
zfree(rc.font_menuheader.name);
zfree(rc.font_menuitem.name); zfree(rc.font_menuitem.name);
zfree(rc.font_osd.name); zfree(rc.font_osd.name);
zfree(rc.theme_name); zfree(rc.theme_name);

View file

@ -138,6 +138,14 @@ menu_update_width(struct menu *menu)
scaled_font_buffer_set_max_width(item->normal.buffer, scaled_font_buffer_set_max_width(item->normal.buffer,
max_width); max_width);
} }
if (theme->menu_title_text_justify == LAB_JUSTIFY_CENTER) {
int x, y;
x = (max_width - theme->menu_item_padding_x -
item->native_width) / 2;
x = x < 0 ? 0 : x;
y = (theme->menu_item_height - item->normal.buffer->height) / 2;
wlr_scene_node_set_position(item->normal.text, x, y);
}
} }
if (item->selectable) { if (item->selectable) {
@ -290,9 +298,16 @@ separator_create(struct menu *menu, const char *label)
struct server *server = menu->server; struct server *server = menu->server;
struct theme *theme = server->theme; struct theme *theme = server->theme;
/*
* Convert empty label ie "", to a regular separator line
* if one desires an empty title line then set label to " "
*/
if (label && !strlen(label)) {
menuitem->type = LAB_MENU_SEPARATOR_LINE;
}
if (menuitem->type == LAB_MENU_TITLE) { if (menuitem->type == LAB_MENU_TITLE) {
menuitem->height = theme->menu_item_height; menuitem->height = theme->menu_item_height;
menuitem->native_width = font_width(&rc.font_menuitem, label); menuitem->native_width = font_width(&rc.font_menuheader, label);
} else if (menuitem->type == LAB_MENU_SEPARATOR_LINE) { } 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;
@ -309,6 +324,8 @@ separator_create(struct menu *menu, const char *label)
/* Item background nodes */ /* Item background nodes */
float *bg_color = menuitem->type == LAB_MENU_TITLE float *bg_color = menuitem->type == LAB_MENU_TITLE
? theme->menu_title_bg_color : theme->menu_items_bg_color; ? theme->menu_title_bg_color : theme->menu_items_bg_color;
float *text_color = menuitem->type == LAB_MENU_TITLE
? theme->menu_title_text_color : theme->menu_items_text_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, bg_color)->node; menu->size.width, menuitem->height, bg_color)->node;
@ -325,8 +342,8 @@ separator_create(struct menu *menu, const char *label)
menuitem->normal.text = &menuitem->normal.buffer->scene_buffer->node; menuitem->normal.text = &menuitem->normal.buffer->scene_buffer->node;
/* Font buffer */ /* Font buffer */
scaled_font_buffer_update(menuitem->normal.buffer, label, scaled_font_buffer_update(menuitem->normal.buffer, label,
menuitem->native_width, &rc.font_menuitem, menuitem->native_width, &rc.font_menuheader,
theme->menu_items_text_color, bg_color, /* arrow */ NULL); text_color, bg_color, /* arrow */ NULL);
/* Center font nodes */ /* Center font nodes */
int x, y; int x, y;
x = theme->menu_item_padding_x; x = theme->menu_item_padding_x;

View file

@ -487,6 +487,7 @@ theme_builtin(struct theme *theme, struct server *server)
parse_hexstr("#000000", theme->window_active_label_text_color); parse_hexstr("#000000", theme->window_active_label_text_color);
parse_hexstr("#000000", theme->window_inactive_label_text_color); parse_hexstr("#000000", theme->window_inactive_label_text_color);
theme->window_label_text_justify = parse_justification("Center"); theme->window_label_text_justify = parse_justification("Center");
theme->menu_title_text_justify = parse_justification("Left");
theme->window_button_width = 26; theme->window_button_width = 26;
@ -529,6 +530,7 @@ theme_builtin(struct theme *theme, struct server *server)
parse_hexstr("#888888", theme->menu_separator_color); parse_hexstr("#888888", theme->menu_separator_color);
parse_hexstr("#589bda", theme->menu_title_bg_color); parse_hexstr("#589bda", theme->menu_title_bg_color);
parse_hexstr("#000000", theme->menu_title_text_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;
@ -606,6 +608,9 @@ entry(struct theme *theme, const char *key, const char *value)
if (match_glob(key, "menu.items.padding.y")) { if (match_glob(key, "menu.items.padding.y")) {
theme->menu_item_padding_y = atoi(value); theme->menu_item_padding_y = atoi(value);
} }
if (match_glob(key, "menu.title.text.justify")) {
theme->menu_title_text_justify = parse_justification(value);
}
if (match_glob(key, "menu.overlap.x")) { if (match_glob(key, "menu.overlap.x")) {
theme->menu_overlap_x = atoi(value); theme->menu_overlap_x = atoi(value);
} }
@ -772,6 +777,10 @@ entry(struct theme *theme, const char *key, const char *value)
parse_hexstr(value, theme->menu_title_bg_color); parse_hexstr(value, theme->menu_title_bg_color);
} }
if (match_glob(key, "menu.title.text.color")) {
parse_hexstr(value, theme->menu_title_text_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);
} }