add -custom-title and -center-title options

This commit is contained in:
kolunmi 2023-03-18 10:58:33 -07:00
parent c91e728fd6
commit b1e0f996c2
2 changed files with 191 additions and 114 deletions

View File

@ -1,14 +1,21 @@
// use ipc functionality // use ipc functionality
static bool ipc = false; static bool ipc = false;
// initially hide all bars
// bar properties
static bool hidden = false; static bool hidden = false;
// initially draw all bars at the bottom
static bool bottom = false; static bool bottom = false;
// hide vacant tags
static bool hide_vacant = false; static bool hide_vacant = false;
// vertical pixel padding above and below text
static uint32_t vertical_padding = 1;
// allow in-line color commands in status text
static bool status_commands = true;
// center title text
static bool center_title = false;
// use title space as status text element
static bool custom_title = false;
// font // font
static char *fontstr = "monospace:size=16"; static char *fontstr = "monospace:size=16";
// tag names if ipc is disabled // tag names if ipc is disabled
static char *tags_noipc[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static char *tags_noipc[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
@ -21,12 +28,3 @@ static pixman_color_t inactive_fg_color = { .red = 0xbbbb, .green = 0xbbbb, .blu
static pixman_color_t inactive_bg_color = { .red = 0x2222, .green = 0x2222, .blue = 0x2222, .alpha = 0xffff, }; static pixman_color_t inactive_bg_color = { .red = 0x2222, .green = 0x2222, .blue = 0x2222, .alpha = 0xffff, };
static pixman_color_t urgent_fg_color = { .red = 0x2222, .green = 0x2222, .blue = 0x2222, .alpha = 0xffff, }; static pixman_color_t urgent_fg_color = { .red = 0x2222, .green = 0x2222, .blue = 0x2222, .alpha = 0xffff, };
static pixman_color_t urgent_bg_color = { .red = 0xeeee, .green = 0xeeee, .blue = 0xeeee, .alpha = 0xffff, }; static pixman_color_t urgent_bg_color = { .red = 0xeeee, .green = 0xeeee, .blue = 0xeeee, .alpha = 0xffff, };
// vertical pixel padding above and below text
static uint32_t vertical_padding = 1;
// allow in-line color commands in status text
static bool status_commands = true;
// do not display current window title
static bool no_title = false;

281
dwlb.c
View File

@ -80,8 +80,10 @@
" -no-hide-vacant-tags display empty and inactive tags\n" \ " -no-hide-vacant-tags display empty and inactive tags\n" \
" -status-commands enable in-line commands in status text\n" \ " -status-commands enable in-line commands in status text\n" \
" -no-status-commands disable in-line commands in status text\n" \ " -no-status-commands disable in-line commands in status text\n" \
" -no-title do not display current window title\n" \ " -center-title center title text on bar\n" \
" -no-no-title display current window title\n" \ " -no-center-title do not center title text on bar\n" \
" -custom-title do not display window title and treat the area as another status text element; see -title command\n" \
" -no-custom-title display current window title as normal\n" \
" -font [FONT] specify a font\n" \ " -font [FONT] specify a font\n" \
" -tags [NUMBER] [FIRST]...[LAST] if ipc is disabled, specify custom tag names\n" \ " -tags [NUMBER] [FIRST]...[LAST] if ipc is disabled, specify custom tag names\n" \
" -vertical-padding [PIXELS] specify vertical pixel padding above and below text\n" \ " -vertical-padding [PIXELS] specify vertical pixel padding above and below text\n" \
@ -93,6 +95,7 @@
" -urgent-bg-color [COLOR] specify background color of urgent tags\n" \ " -urgent-bg-color [COLOR] specify background color of urgent tags\n" \
"Commands\n" \ "Commands\n" \
" -status [OUTPUT] [TEXT] set status text\n" \ " -status [OUTPUT] [TEXT] set status text\n" \
" -title [OUTPUT] [TEXT] set title text, if -custom-title is enabled\n" \
" -show [OUTPUT] show bar\n" \ " -show [OUTPUT] show bar\n" \
" -hide [OUTPUT] hide bar\n" \ " -hide [OUTPUT] hide bar\n" \
" -toggle-visibility [OUTPUT] toggle bar visibility\n" \ " -toggle-visibility [OUTPUT] toggle bar visibility\n" \
@ -107,14 +110,22 @@ typedef struct {
pixman_color_t color; pixman_color_t color;
bool bg; bool bg;
char *start; char *start;
} StatusColor; } Color;
typedef struct { typedef struct {
uint32_t btn; uint32_t btn;
uint32_t x1; uint32_t x1;
uint32_t x2; uint32_t x2;
char command[128]; char command[128];
} StatusButton; } Button;
typedef struct {
char text[2048];
Color *colors;
uint32_t colors_l, colors_c;
Button *buttons;
uint32_t buttons_l, buttons_c;
} CustomText;
typedef struct { typedef struct {
struct wl_output *wl_output; struct wl_output *wl_output;
@ -132,14 +143,9 @@ typedef struct {
uint32_t stride, bufsize; uint32_t stride, bufsize;
uint32_t mtags, ctags, urg, sel; uint32_t mtags, ctags, urg, sel;
char layout[32]; char *layout, *window_title;
uint32_t layout_idx, last_layout_idx; uint32_t layout_idx, last_layout_idx;
char title[1024], status[1024]; CustomText title, status;
StatusColor *status_colors;
uint32_t status_colors_l, status_colors_c;
StatusButton *status_buttons;
uint32_t status_buttons_l, status_buttons_c;
bool hidden, bottom; bool hidden, bottom;
bool redraw; bool redraw;
@ -230,7 +236,7 @@ draw_text(char *text,
uint32_t max_x, uint32_t max_x,
uint32_t buf_height, uint32_t buf_height,
uint32_t padding, uint32_t padding,
StatusColor *colors, Color *colors,
uint32_t colors_l) uint32_t colors_l)
{ {
if (!text || !*text || !max_x) if (!text || !*text || !max_x)
@ -413,19 +419,34 @@ draw_frame(Bar *bar)
&inactive_fg_color, &inactive_bg_color, bar->width, &inactive_fg_color, &inactive_bg_color, bar->width,
bar->height, bar->textpadding, NULL, 0); bar->height, bar->textpadding, NULL, 0);
uint32_t status_width = TEXT_WIDTH(bar->status, bar->width - x, bar->textpadding); uint32_t status_width = TEXT_WIDTH(bar->status.text, bar->width - x, bar->textpadding);
draw_text(bar->status, bar->width - status_width, y, foreground, draw_text(bar->status.text, bar->width - status_width, y, foreground,
background, &inactive_fg_color, &inactive_bg_color, background, &inactive_fg_color, &inactive_bg_color,
bar->width, bar->height, bar->textpadding, bar->width, bar->height, bar->textpadding,
bar->status_colors, bar->status_colors_l); bar->status.colors, bar->status.colors_l);
if (!no_title) { uint32_t nx;
x = draw_text(bar->title, x, y, foreground, background, if (center_title) {
bar->sel ? &active_fg_color : &inactive_fg_color, uint32_t title_width = TEXT_WIDTH(custom_title ? bar->title.text : bar->window_title, bar->width - status_width - x, 0);
bar->sel ? &active_bg_color : &inactive_bg_color, nx = MAX(x, MIN((bar->width - title_width) / 2, bar->width - status_width - title_width));
bar->width - status_width, bar->height, bar->textpadding, } else {
NULL, 0); nx = MIN(x + bar->textpadding, bar->width - status_width);
} }
pixman_image_fill_boxes(PIXMAN_OP_SRC, background,
bar->sel ? &active_bg_color : &inactive_bg_color, 1,
&(pixman_box32_t){
.x1 = x, .x2 = nx,
.y1 = 0, .y2 = bar->height
});
x = nx;
x = draw_text(custom_title ? bar->title.text : bar->window_title,
x, y, foreground, background,
bar->sel ? &active_fg_color : &inactive_fg_color,
bar->sel ? &active_bg_color : &inactive_bg_color,
bar->width - status_width, bar->height, 0,
custom_title ? bar->title.colors : NULL,
custom_title ? bar->title.colors_l : 0);
pixman_image_fill_boxes(PIXMAN_OP_SRC, background, pixman_image_fill_boxes(PIXMAN_OP_SRC, background,
bar->sel ? &active_bg_color : &inactive_bg_color, 1, bar->sel ? &active_bg_color : &inactive_bg_color, 1,
@ -637,17 +658,32 @@ pointer_frame(void *data, struct wl_pointer *pointer)
znet_tapesoftware_dwl_wm_monitor_v1_set_layout(seat->bar->dwl_wm_monitor, 2); znet_tapesoftware_dwl_wm_monitor_v1_set_layout(seat->bar->dwl_wm_monitor, 2);
} }
} else { } else {
uint32_t status_x = seat->bar->width - TEXT_WIDTH(seat->bar->status, seat->bar->width - x, seat->bar->textpadding); uint32_t status_x = seat->bar->width - TEXT_WIDTH(seat->bar->status.text, seat->bar->width - x, seat->bar->textpadding);
if (seat->pointer_x < status_x) { if (seat->pointer_x < status_x) {
/* Clicked on title */ /* Clicked on title */
if (custom_title) {
if (center_title) {
uint32_t title_width = TEXT_WIDTH(seat->bar->title.text, status_x - x, 0);
x = MAX(x, MIN((seat->bar->width - title_width) / 2, status_x - title_width));
} else {
x = MIN(x + seat->bar->textpadding, status_x);
}
for (i = 0; i < seat->bar->title.buttons_l; i++) {
if (seat->pointer_button == seat->bar->title.buttons[i].btn
&& seat->pointer_x >= x + seat->bar->title.buttons[i].x1
&& seat->pointer_x < x + seat->bar->title.buttons[i].x2) {
shell_command(seat->bar->title.buttons[i].command);
break;
}
}
}
} else { } else {
/* Clicked on status */ /* Clicked on status */
for (i = 0; i < seat->bar->status_buttons_l; i++) { for (i = 0; i < seat->bar->status.buttons_l; i++) {
if (seat->pointer_button == seat->bar->status_buttons[i].btn if (seat->pointer_button == seat->bar->status.buttons[i].btn
&& seat->pointer_x >= status_x + seat->bar->textpadding + seat->bar->status_buttons[i].x1 && seat->pointer_x >= status_x + seat->bar->textpadding + seat->bar->status.buttons[i].x1
&& seat->pointer_x < status_x + seat->bar->textpadding + seat->bar->status_buttons[i].x2) { && seat->pointer_x < status_x + seat->bar->textpadding + seat->bar->status.buttons[i].x2) {
shell_command(seat->bar->status_buttons[i].command); shell_command(seat->bar->status.buttons[i].command);
break; break;
} }
} }
@ -794,27 +830,26 @@ dwl_wm_monitor_layout(void *data, struct znet_tapesoftware_dwl_wm_monitor_v1 *dw
{ {
Bar *bar = (Bar *)data; Bar *bar = (Bar *)data;
if (strcmp(bar->layout, layouts[layout]) != 0) { bar->layout = layouts[layout];
snprintf(bar->layout, sizeof bar->layout, "%s", layouts[layout]); bar->last_layout_idx = bar->layout_idx;
bar->last_layout_idx = bar->layout_idx; bar->layout_idx = layout;
bar->layout_idx = layout; bar->redraw = true;
bar->redraw = true;
}
} }
static void static void
dwl_wm_monitor_title(void *data, struct znet_tapesoftware_dwl_wm_monitor_v1 *dwl_wm_monitor, dwl_wm_monitor_title(void *data, struct znet_tapesoftware_dwl_wm_monitor_v1 *dwl_wm_monitor,
const char *title) const char *title)
{ {
if (no_title) if (custom_title)
return; return;
Bar *bar = (Bar *)data; Bar *bar = (Bar *)data;
if (strcmp(bar->title, title) != 0) { if (bar->window_title)
snprintf(bar->title, sizeof bar->title, "%s", title); free(bar->window_title);
bar->redraw = true; if (!(bar->window_title = strdup(title)))
} EDIE("strdup");
bar->redraw = true;
} }
static void static void
@ -872,9 +907,6 @@ setup_bar(Bar *bar)
bar->bottom = bottom; bar->bottom = bottom;
bar->hidden = hidden; bar->hidden = hidden;
if (!ipc)
snprintf(bar->layout, sizeof bar->layout, "[]=");
bar->xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, bar->wl_output); bar->xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, bar->wl_output);
if (!bar->xdg_output) if (!bar->xdg_output)
DIE("Could not create xdg_output"); DIE("Could not create xdg_output");
@ -931,14 +963,20 @@ handle_global(void *data, struct wl_registry *registry,
static void static void
teardown_bar(Bar *bar) teardown_bar(Bar *bar)
{ {
if (bar->status.colors)
free(bar->status.colors);
if (bar->status.buttons)
free(bar->status.buttons);
if (bar->title.colors)
free(bar->title.colors);
if (bar->title.buttons)
free(bar->title.buttons);
if (!ipc && bar->layout)
free(bar->layout);
if (ipc) if (ipc)
znet_tapesoftware_dwl_wm_monitor_v1_destroy(bar->dwl_wm_monitor); znet_tapesoftware_dwl_wm_monitor_v1_destroy(bar->dwl_wm_monitor);
if (bar->xdg_output_name) if (bar->xdg_output_name)
free(bar->xdg_output_name); free(bar->xdg_output_name);
if (bar->status_colors)
free(bar->status_colors);
if (bar->status_buttons)
free(bar->status_buttons);
if (!bar->hidden) { if (!bar->hidden) {
zwlr_layer_surface_v1_destroy(bar->layer_surface); zwlr_layer_surface_v1_destroy(bar->layer_surface);
wl_surface_destroy(bar->wl_surface); wl_surface_destroy(bar->wl_surface);
@ -1065,15 +1103,19 @@ read_stdin(void)
bar->redraw = true; bar->redraw = true;
} }
} else if (!strcmp(wordbeg, "layout")) { } else if (!strcmp(wordbeg, "layout")) {
if (strcmp(bar->layout, wordend) != 0) { if (bar->layout)
snprintf(bar->layout, sizeof bar->layout, "%s", wordend); free(bar->layout);
bar->redraw = true; if (!(bar->layout = strdup(wordend)))
} EDIE("strdup");
bar->redraw = true;
} else if (!strcmp(wordbeg, "title")) { } else if (!strcmp(wordbeg, "title")) {
if (strcmp(bar->title, wordend) != 0) { if (custom_title)
snprintf(bar->title, sizeof bar->title, "%s", wordend); continue;
bar->redraw = true; if (bar->window_title)
} free(bar->window_title);
if (!(bar->window_title = strdup(wordend)))
EDIE("strdup");
bar->redraw = true;
} else if (!strcmp(wordbeg, "selmon")) { } else if (!strcmp(wordbeg, "selmon")) {
ADVANCE(); ADVANCE();
if ((val = atoi(wordbeg)) != bar->sel) { if ((val = atoi(wordbeg)) != bar->sel) {
@ -1140,9 +1182,9 @@ parse_color(const char *str, pixman_color_t *clr)
} }
static void static void
set_status(Bar *bar, char *text) parse_into_customtext(CustomText *ct, char *text)
{ {
bar->status_colors_l = bar->status_buttons_l = 0; ct->colors_l = ct->buttons_l = 0;
if (status_commands) { if (status_commands) {
uint32_t codepoint; uint32_t codepoint;
@ -1151,11 +1193,11 @@ set_status(Bar *bar, char *text)
uint32_t x = 0; uint32_t x = 0;
size_t str_pos = 0; size_t str_pos = 0;
StatusButton *left_button = NULL; Button *left_button = NULL;
StatusButton *middle_button = NULL; Button *middle_button = NULL;
StatusButton *right_button = NULL; Button *right_button = NULL;
for (char *p = text; *p && str_pos < sizeof(bar->status) - 1; p++) { for (char *p = text; *p && str_pos < sizeof(ct->text) - 1; p++) {
if (state == UTF8_ACCEPT && *p == '^') { if (state == UTF8_ACCEPT && *p == '^') {
p++; p++;
if (*p != '^') { if (*p != '^') {
@ -1166,29 +1208,29 @@ set_status(Bar *bar, char *text)
*end = '\0'; *end = '\0';
if (!strcmp(p, "bg")) { if (!strcmp(p, "bg")) {
StatusColor *status_color; Color *color;
ARRAY_APPEND(bar->status_colors, bar->status_colors_l, bar->status_colors_c, status_color); ARRAY_APPEND(ct->colors, ct->colors_l, ct->colors_c, color);
if (!*arg) if (!*arg)
status_color->color = inactive_bg_color; color->color = inactive_bg_color;
else else
parse_color(arg, &status_color->color); parse_color(arg, &color->color);
status_color->bg = true; color->bg = true;
status_color->start = bar->status + str_pos; color->start = ct->text + str_pos;
} else if (!strcmp(p, "fg")) { } else if (!strcmp(p, "fg")) {
StatusColor *status_color; Color *color;
ARRAY_APPEND(bar->status_colors, bar->status_colors_l, bar->status_colors_c, status_color); ARRAY_APPEND(ct->colors, ct->colors_l, ct->colors_c, color);
if (!*arg) if (!*arg)
status_color->color = inactive_fg_color; color->color = inactive_fg_color;
else else
parse_color(arg, &status_color->color); parse_color(arg, &color->color);
status_color->bg = false; color->bg = false;
status_color->start = bar->status + str_pos; color->start = ct->text + str_pos;
} else if (!strcmp(p, "lm")) { } else if (!strcmp(p, "lm")) {
if (left_button) { if (left_button) {
left_button->x2 = x; left_button->x2 = x;
left_button = NULL; left_button = NULL;
} else if (*arg) { } else if (*arg) {
ARRAY_APPEND(bar->status_buttons, bar->status_buttons_l, bar->status_buttons_c, left_button); ARRAY_APPEND(ct->buttons, ct->buttons_l, ct->buttons_c, left_button);
left_button->btn = BTN_LEFT; left_button->btn = BTN_LEFT;
snprintf(left_button->command, sizeof left_button->command, "%s", arg); snprintf(left_button->command, sizeof left_button->command, "%s", arg);
left_button->x1 = x; left_button->x1 = x;
@ -1198,7 +1240,7 @@ set_status(Bar *bar, char *text)
middle_button->x2 = x; middle_button->x2 = x;
middle_button = NULL; middle_button = NULL;
} else if (*arg) { } else if (*arg) {
ARRAY_APPEND(bar->status_buttons, bar->status_buttons_l, bar->status_buttons_c, middle_button); ARRAY_APPEND(ct->buttons, ct->buttons_l, ct->buttons_c, middle_button);
middle_button->btn = BTN_MIDDLE; middle_button->btn = BTN_MIDDLE;
snprintf(middle_button->command, sizeof middle_button->command, "%s", arg); snprintf(middle_button->command, sizeof middle_button->command, "%s", arg);
middle_button->x1 = x; middle_button->x1 = x;
@ -1208,7 +1250,7 @@ set_status(Bar *bar, char *text)
right_button->x2 = x; right_button->x2 = x;
right_button = NULL; right_button = NULL;
} else if (*arg) { } else if (*arg) {
ARRAY_APPEND(bar->status_buttons, bar->status_buttons_l, bar->status_buttons_c, right_button); ARRAY_APPEND(ct->buttons, ct->buttons_l, ct->buttons_c, right_button);
right_button->btn = BTN_RIGHT; right_button->btn = BTN_RIGHT;
snprintf(right_button->command, sizeof right_button->command, "%s", arg); snprintf(right_button->command, sizeof right_button->command, "%s", arg);
right_button->x1 = x; right_button->x1 = x;
@ -1223,7 +1265,7 @@ set_status(Bar *bar, char *text)
} }
} }
bar->status[str_pos++] = *p; ct->text[str_pos++] = *p;
if (utf8decode(&state, &codepoint, *p)) if (utf8decode(&state, &codepoint, *p))
continue; continue;
@ -1247,9 +1289,28 @@ set_status(Bar *bar, char *text)
if (right_button) if (right_button)
right_button->x2 = x; right_button->x2 = x;
bar->status[str_pos] = '\0'; ct->text[str_pos] = '\0';
} else { } else {
snprintf(bar->status, sizeof bar->status, "%s", text); snprintf(ct->text, sizeof ct->text, "%s", text);
}
}
static void
copy_customtext(CustomText *from, CustomText *to)
{
snprintf(to->text, sizeof to->text, "%s", from->text);
to->colors_l = to->buttons_l = 0;
for (uint32_t i = 0; i < from->colors_l; i++) {
Color *color;
ARRAY_APPEND(to->colors, to->colors_l, to->colors_c, color);
color->color = from->colors[i].color;
color->bg = from->colors[i].bg;
color->start = from->colors[i].start - (char *)&from->text + (char *)&to->text;
}
for (uint32_t i = 0; i < from->buttons_l; i++) {
Button *button;
ARRAY_APPEND(to->buttons, to->buttons_l, to->buttons_c, button);
*button = from->buttons[i];
} }
} }
@ -1305,29 +1366,33 @@ read_socket(void)
Bar *first = NULL; Bar *first = NULL;
wl_list_for_each(bar, &bar_list, link) { wl_list_for_each(bar, &bar_list, link) {
if (first) { if (first) {
/* Copy over parsed status information to other bars */ copy_customtext(&first->status, &bar->status);
snprintf(bar->status, sizeof bar->status, "%s", first->status);
bar->status_colors_l = bar->status_buttons_l = 0;
for (uint32_t i = 0; i < first->status_colors_l; i++) {
StatusColor *status_color;
ARRAY_APPEND(bar->status_colors, bar->status_colors_l, bar->status_colors_c, status_color);
status_color->color = first->status_colors[i].color;
status_color->bg = first->status_colors[i].bg;
status_color->start = first->status_colors[i].start - (char *)&first->status + (char *)&bar->status;
}
for (uint32_t i = 0; i < first->status_buttons_l; i++) {
StatusButton *status_button;
ARRAY_APPEND(bar->status_buttons, bar->status_buttons_l, bar->status_buttons_c, status_button);
*status_button = first->status_buttons[i];
}
} else { } else {
set_status(bar, wordend); parse_into_customtext(&bar->status, wordend);
first = bar; first = bar;
} }
bar->redraw = true; bar->redraw = true;
} }
} else { } else {
set_status(bar, wordend); parse_into_customtext(&bar->status, wordend);
bar->redraw = true;
}
} else if (!strcmp(wordbeg, "title")) {
if (!custom_title || !*wordend)
return;
if (all) {
Bar *first = NULL;
wl_list_for_each(bar, &bar_list, link) {
if (first) {
copy_customtext(&first->title, &bar->title);
} else {
parse_into_customtext(&bar->title, wordend);
first = bar;
}
bar->redraw = true;
}
} else {
parse_into_customtext(&bar->title, wordend);
bar->redraw = true; bar->redraw = true;
} }
} else if (!strcmp(wordbeg, "show")) { } else if (!strcmp(wordbeg, "show")) {
@ -1507,6 +1572,11 @@ main(int argc, char **argv)
DIE("Option -status requires two arguments"); DIE("Option -status requires two arguments");
client_send_command(&sock_address, argv[i], "status", argv[i + 1]); client_send_command(&sock_address, argv[i], "status", argv[i + 1]);
return 0; return 0;
} else if (!strcmp(argv[i], "-title")) {
if (++i + 1 >= argc)
DIE("Option -title requires two arguments");
client_send_command(&sock_address, argv[i], "title", argv[i + 1]);
return 0;
} else if (!strcmp(argv[i], "-show")) { } else if (!strcmp(argv[i], "-show")) {
if (++i >= argc) if (++i >= argc)
DIE("Option -show requires an argument"); DIE("Option -show requires an argument");
@ -1557,10 +1627,14 @@ main(int argc, char **argv)
status_commands = true; status_commands = true;
} else if (!strcmp(argv[i], "-no-status-commands")) { } else if (!strcmp(argv[i], "-no-status-commands")) {
status_commands = false; status_commands = false;
} else if (!strcmp(argv[i], "-no-title")) { } else if (!strcmp(argv[i], "-center-title")) {
no_title = true; center_title = true;
} else if (!strcmp(argv[i], "-no-no-title")) { } else if (!strcmp(argv[i], "-no-center-title")) {
no_title = false; center_title = false;
} else if (!strcmp(argv[i], "-custom-title")) {
custom_title = true;
} else if (!strcmp(argv[i], "-no-custom-title")) {
custom_title = false;
} else if (!strcmp(argv[i], "-font")) { } else if (!strcmp(argv[i], "-font")) {
if (++i >= argc) if (++i >= argc)
DIE("Option -font requires an argument"); DIE("Option -font requires an argument");
@ -1727,6 +1801,11 @@ main(int argc, char **argv)
free(tags[i]); free(tags[i]);
free(tags); free(tags);
} }
if (layouts) {
for (uint32_t i = 0; i < layouts_l; i++)
free(layouts[i]);
free(layouts);
}
wl_list_for_each_safe(bar, bar2, &bar_list, link) wl_list_for_each_safe(bar, bar2, &bar_list, link)
teardown_bar(bar); teardown_bar(bar);