forked from external/yambar
This allows us to a) move away from cairo's "toy" API, and b) let the user specify font options in a single font "name" string: Serif:size=10:weight=bold:slant=italic This also allows us to simplify the font code significantly (except for the fontconfig parts...); the font no longer sets itself in a cairo surface - font users do that; the font simply returns a cairo_scaled_font_t. Furthermore, font_clone() has now been simplified to basically just refcount the scaled font. I.e. there's no need to run the full constructor and lookup and instantiate the cairo scaled font again.
731 lines
24 KiB
C
731 lines
24 KiB
C
#include "config.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include "color.h"
|
|
|
|
#include "decoration.h"
|
|
#include "decorations/background.h"
|
|
#include "decorations/stack.h"
|
|
#include "decorations/underline.h"
|
|
|
|
#include "particle.h"
|
|
#include "particles/empty.h"
|
|
#include "particles/list.h"
|
|
#include "particles/map.h"
|
|
#include "particles/progress_bar.h"
|
|
#include "particles/ramp.h"
|
|
#include "particles/string.h"
|
|
|
|
#include "module.h"
|
|
#include "modules/alsa.h"
|
|
#include "modules/backlight.h"
|
|
#include "modules/battery.h"
|
|
#include "modules/clock.h"
|
|
#include "modules/i3.h"
|
|
#include "modules/label.h"
|
|
#include "modules/mpd.h"
|
|
#include "modules/network.h"
|
|
#include "modules/removables.h"
|
|
#include "modules/xkb.h"
|
|
#include "modules/xwindow.h"
|
|
|
|
#include "config-verify.h"
|
|
|
|
static uint8_t
|
|
hex_nibble(char hex)
|
|
{
|
|
assert((hex >= '0' && hex <= '9') ||
|
|
(hex >= 'a' && hex <= 'f') ||
|
|
(hex >= 'A' && hex <= 'F'));
|
|
|
|
if (hex >= '0' && hex <= '9')
|
|
return hex - '0';
|
|
else if (hex >= 'a' && hex <= 'f')
|
|
return hex - 'a' + 10;
|
|
else
|
|
return hex - 'A' + 10;
|
|
}
|
|
|
|
static uint8_t
|
|
hex_byte(const char hex[2])
|
|
{
|
|
uint8_t upper = hex_nibble(hex[0]);
|
|
uint8_t lower = hex_nibble(hex[1]);
|
|
return upper << 4 | lower;
|
|
}
|
|
|
|
static struct rgba
|
|
color_from_hexstr(const char *hex)
|
|
{
|
|
assert(strlen(hex) == 8);
|
|
uint8_t red = hex_byte(&hex[0]);
|
|
uint8_t green = hex_byte(&hex[2]);
|
|
uint8_t blue = hex_byte(&hex[4]);
|
|
uint8_t alpha = hex_byte(&hex[6]);
|
|
|
|
struct rgba rgba = {
|
|
(double)red / 255.0,
|
|
(double)green / 255.0,
|
|
(double)blue / 255.0,
|
|
(double)alpha / 255.0
|
|
};
|
|
|
|
assert(rgba.red >= 0.0 && rgba.red <= 1.0);
|
|
assert(rgba.green >= 0.0 && rgba.green <= 1.0);
|
|
assert(rgba.blue >= 0.0 && rgba.blue <= 1.0);
|
|
assert(rgba.alpha >= 0.0 && rgba.alpha <= 1.0);
|
|
|
|
return rgba;
|
|
}
|
|
|
|
static struct font *
|
|
font_from_config(const struct yml_node *node)
|
|
{
|
|
const struct yml_node *family = yml_get_value(node, "family");
|
|
return font_new(family != NULL ? yml_value_as_string(family) : "monospace");
|
|
}
|
|
|
|
static struct deco *
|
|
deco_background_from_config(const struct yml_node *node)
|
|
{
|
|
assert(yml_is_dict(node));
|
|
|
|
const struct yml_node *color = yml_get_value(node, "color");
|
|
assert(yml_is_scalar(color));
|
|
|
|
return deco_background(color_from_hexstr(yml_value_as_string(color)));
|
|
}
|
|
|
|
static struct deco *
|
|
deco_underline_from_config(const struct yml_node *node)
|
|
{
|
|
assert(yml_is_dict(node));
|
|
|
|
const struct yml_node *size = yml_get_value(node, "size");
|
|
const struct yml_node *color = yml_get_value(node, "color");
|
|
assert(yml_is_scalar(size));
|
|
assert(yml_is_scalar(color));
|
|
|
|
return deco_underline(
|
|
yml_value_as_int(size), color_from_hexstr(yml_value_as_string(color)));
|
|
}
|
|
|
|
static struct deco *deco_from_config(const struct yml_node *node);
|
|
|
|
static struct deco *
|
|
deco_stack_from_config(const struct yml_node *node)
|
|
{
|
|
assert(yml_is_list(node));
|
|
|
|
size_t count = yml_list_length(node);
|
|
assert(count > 0);
|
|
|
|
struct deco *decos[count];
|
|
size_t idx = 0;
|
|
|
|
for (struct yml_list_iter it = yml_list_iter(node);
|
|
it.node != NULL;
|
|
yml_list_next(&it), idx++)
|
|
{
|
|
decos[idx] = deco_from_config(it.node);
|
|
}
|
|
|
|
return deco_stack(decos, count);
|
|
}
|
|
|
|
static struct deco *
|
|
deco_from_config(const struct yml_node *node)
|
|
{
|
|
assert(yml_is_dict(node));
|
|
assert(yml_dict_length(node) == 1);
|
|
|
|
struct yml_dict_iter it = yml_dict_iter(node);
|
|
const struct yml_node *deco_type = it.key;
|
|
const struct yml_node *deco_data = it.value;
|
|
|
|
assert(yml_is_scalar(deco_type));
|
|
|
|
const char *type = yml_value_as_string(deco_type);
|
|
|
|
if (strcmp(type, "background") == 0)
|
|
return deco_background_from_config(deco_data);
|
|
else if (strcmp(type, "underline") == 0)
|
|
return deco_underline_from_config(deco_data);
|
|
else if (strcmp(type, "stack") == 0)
|
|
return deco_stack_from_config(deco_data);
|
|
else
|
|
assert(false);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static struct particle *
|
|
particle_empty_from_config(const struct yml_node *node,
|
|
const struct font *parent_font,
|
|
int left_margin, int right_margin,
|
|
const char *on_click_template)
|
|
{
|
|
return particle_empty_new(left_margin, right_margin, on_click_template);
|
|
}
|
|
|
|
static struct particle *
|
|
particle_string_from_config(const struct yml_node *node,
|
|
const struct font *parent_font,
|
|
int left_margin, int right_margin,
|
|
const char *on_click_template)
|
|
{
|
|
assert(yml_is_dict(node));
|
|
|
|
const struct yml_node *text = yml_get_value(node, "text");
|
|
const struct yml_node *max = yml_get_value(node, "max");
|
|
const struct yml_node *font = yml_get_value(node, "font");
|
|
const struct yml_node *foreground = yml_get_value(node, "foreground");
|
|
|
|
assert(text != NULL && yml_is_scalar(text));
|
|
assert(max == NULL || yml_value_is_int(max));
|
|
|
|
struct rgba fg_color = foreground != NULL
|
|
? color_from_hexstr(yml_value_as_string(foreground)) :
|
|
(struct rgba){1.0, 1.0, 1.0, 1.0};
|
|
|
|
return particle_string_new(
|
|
yml_value_as_string(text),
|
|
max != NULL ? yml_value_as_int(max) : 0,
|
|
font != NULL ? font_from_config(font) : font_clone(parent_font),
|
|
fg_color, left_margin, right_margin, on_click_template);
|
|
}
|
|
|
|
static struct particle * particle_from_config(
|
|
const struct yml_node *node, const struct font *parent_font);
|
|
|
|
static struct particle *
|
|
particle_list_from_config(const struct yml_node *node,
|
|
const struct font *parent_font,
|
|
int left_margin, int right_margin,
|
|
const char *on_click_template)
|
|
{
|
|
const struct yml_node *items = yml_get_value(node, "items");
|
|
|
|
const struct yml_node *spacing = yml_get_value(node, "spacing");
|
|
const struct yml_node *_left_spacing = yml_get_value(node, "left_spacing");
|
|
const struct yml_node *_right_spacing = yml_get_value(node, "right_spacing");
|
|
|
|
int left_spacing = spacing != NULL ? yml_value_as_int(spacing) :
|
|
_left_spacing != NULL ? yml_value_as_int(_left_spacing) : 0;
|
|
int right_spacing = spacing != NULL ? yml_value_as_int(spacing) :
|
|
_right_spacing != NULL ? yml_value_as_int(_right_spacing) : 2;;
|
|
|
|
size_t count = yml_list_length(items);
|
|
struct particle *parts[count];
|
|
|
|
size_t idx = 0;
|
|
for (struct yml_list_iter it = yml_list_iter(items);
|
|
it.node != NULL;
|
|
yml_list_next(&it), idx++)
|
|
{
|
|
parts[idx] = particle_from_config(it.node, parent_font);
|
|
}
|
|
|
|
return particle_list_new(
|
|
parts, count, left_spacing, right_spacing, left_margin, right_margin,
|
|
on_click_template);
|
|
}
|
|
|
|
static struct particle *
|
|
particle_map_from_config(const struct yml_node *node,
|
|
const struct font *parent_font,
|
|
int left_margin, int right_margin,
|
|
const char *on_click_template)
|
|
{
|
|
const struct yml_node *tag = yml_get_value(node, "tag");
|
|
const struct yml_node *values = yml_get_value(node, "values");
|
|
const struct yml_node *def = yml_get_value(node, "default");
|
|
|
|
assert(yml_is_scalar(tag));
|
|
assert(yml_is_dict(values));
|
|
|
|
struct particle_map particle_map[yml_dict_length(values)];
|
|
|
|
size_t idx = 0;
|
|
for (struct yml_dict_iter it = yml_dict_iter(values);
|
|
it.key != NULL;
|
|
yml_dict_next(&it), idx++)
|
|
{
|
|
particle_map[idx].tag_value = yml_value_as_string(it.key);
|
|
particle_map[idx].particle = particle_from_config(it.value, parent_font);
|
|
assert(particle_map[idx].particle != NULL);
|
|
}
|
|
|
|
struct particle *default_particle = def != NULL
|
|
? particle_from_config(def, parent_font)
|
|
: NULL;
|
|
|
|
return particle_map_new(
|
|
yml_value_as_string(tag), particle_map, yml_dict_length(values),
|
|
default_particle, left_margin, right_margin, on_click_template);
|
|
}
|
|
|
|
static struct particle *
|
|
particle_ramp_from_config(const struct yml_node *node,
|
|
const struct font *parent_font,
|
|
int left_margin, int right_margin,
|
|
const char *on_click_template)
|
|
{
|
|
const struct yml_node *tag = yml_get_value(node, "tag");
|
|
const struct yml_node *items = yml_get_value(node, "items");
|
|
|
|
assert(yml_is_scalar(tag));
|
|
assert(yml_is_list(items));
|
|
|
|
size_t count = yml_list_length(items);
|
|
struct particle *parts[count];
|
|
|
|
size_t idx = 0;
|
|
for (struct yml_list_iter it = yml_list_iter(items);
|
|
it.node != NULL;
|
|
yml_list_next(&it), idx++)
|
|
{
|
|
parts[idx] = particle_from_config(it.node, parent_font);
|
|
}
|
|
|
|
return particle_ramp_new(
|
|
yml_value_as_string(tag), parts, count, left_margin, right_margin,
|
|
on_click_template);
|
|
}
|
|
|
|
static struct particle *
|
|
particle_progress_bar_from_config(const struct yml_node *node,
|
|
const struct font *parent_font,
|
|
int left_margin, int right_margin,
|
|
const char *on_click_template)
|
|
{
|
|
const struct yml_node *tag = yml_get_value(node, "tag");
|
|
const struct yml_node *length = yml_get_value(node, "length");
|
|
const struct yml_node *start = yml_get_value(node, "start");
|
|
const struct yml_node *end = yml_get_value(node, "end");
|
|
const struct yml_node *fill = yml_get_value(node, "fill");
|
|
const struct yml_node *empty = yml_get_value(node, "empty");
|
|
const struct yml_node *indicator = yml_get_value(node, "indicator");
|
|
|
|
assert(tag != NULL && yml_is_scalar(tag));
|
|
assert(length != NULL && yml_is_scalar(length));
|
|
assert(start != NULL);
|
|
assert(end != NULL);
|
|
assert(fill != NULL);
|
|
assert(empty != NULL);
|
|
assert(indicator != NULL);
|
|
|
|
return particle_progress_bar_new(
|
|
yml_value_as_string(tag),
|
|
yml_value_as_int(length),
|
|
particle_from_config(start, parent_font),
|
|
particle_from_config(end, parent_font),
|
|
particle_from_config(fill, parent_font),
|
|
particle_from_config(empty, parent_font),
|
|
particle_from_config(indicator, parent_font),
|
|
left_margin, right_margin, on_click_template);
|
|
}
|
|
|
|
static struct particle *
|
|
particle_simple_list_from_config(const struct yml_node *node,
|
|
const struct font *parent_font)
|
|
{
|
|
assert(yml_is_list(node));
|
|
|
|
size_t count = yml_list_length(node);
|
|
struct particle *parts[count];
|
|
|
|
size_t idx = 0;
|
|
for (struct yml_list_iter it = yml_list_iter(node);
|
|
it.node != NULL;
|
|
yml_list_next(&it), idx++)
|
|
{
|
|
parts[idx] = particle_from_config(it.node, parent_font);
|
|
}
|
|
|
|
return particle_list_new(parts, count, 0, 0, 0, 0, NULL);
|
|
}
|
|
|
|
static struct particle *
|
|
particle_from_config(const struct yml_node *node, const struct font *parent_font)
|
|
{
|
|
if (yml_is_list(node))
|
|
return particle_simple_list_from_config(node, parent_font);
|
|
|
|
assert(yml_is_dict(node));
|
|
assert(yml_dict_length(node) == 1);
|
|
|
|
struct yml_dict_iter pair = yml_dict_iter(node);
|
|
const char *type = yml_value_as_string(pair.key);
|
|
|
|
const struct yml_node *margin = yml_get_value(pair.value, "margin");
|
|
const struct yml_node *left_margin = yml_get_value(pair.value, "left_margin");
|
|
const struct yml_node *right_margin = yml_get_value(pair.value, "right_margin");
|
|
const struct yml_node *on_click = yml_get_value(pair.value, "on_click");
|
|
|
|
assert(margin == NULL || yml_is_scalar(margin));
|
|
assert(left_margin == NULL || yml_is_scalar(left_margin));
|
|
assert(right_margin == NULL || yml_is_scalar(right_margin));
|
|
assert(on_click == NULL || yml_is_scalar(on_click));
|
|
|
|
int left = margin != NULL ? yml_value_as_int(margin) :
|
|
left_margin != NULL ? yml_value_as_int(left_margin) : 0;
|
|
int right = margin != NULL ? yml_value_as_int(margin) :
|
|
right_margin != NULL ? yml_value_as_int(right_margin) : 0;
|
|
|
|
const char *on_click_template
|
|
= on_click != NULL ? yml_value_as_string(on_click) : NULL;
|
|
|
|
struct particle *ret = NULL;
|
|
if (strcmp(type, "empty") == 0)
|
|
ret = particle_empty_from_config(
|
|
pair.value, parent_font, left, right, on_click_template);
|
|
else if (strcmp(type, "string") == 0)
|
|
ret = particle_string_from_config(
|
|
pair.value, parent_font, left, right, on_click_template);
|
|
else if (strcmp(type, "list") == 0)
|
|
ret = particle_list_from_config(
|
|
pair.value, parent_font, left, right, on_click_template);
|
|
else if (strcmp(type, "map") == 0)
|
|
ret = particle_map_from_config(
|
|
pair.value, parent_font, left, right, on_click_template);
|
|
else if (strcmp(type, "ramp") == 0)
|
|
ret = particle_ramp_from_config(
|
|
pair.value, parent_font, left, right, on_click_template);
|
|
else if (strcmp(type, "progress_bar") == 0)
|
|
ret = particle_progress_bar_from_config(
|
|
pair.value, parent_font, left, right, on_click_template);
|
|
else
|
|
assert(false);
|
|
|
|
const struct yml_node *deco_node = yml_get_value(pair.value, "deco");
|
|
assert(deco_node == NULL || yml_is_dict(deco_node));
|
|
|
|
if (deco_node != NULL)
|
|
ret->deco = deco_from_config(deco_node);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static struct module *
|
|
module_label_from_config(const struct yml_node *node, const struct font *parent_font)
|
|
{
|
|
const struct yml_node *c = yml_get_value(node, "content");
|
|
assert(c != NULL);
|
|
return module_label(particle_from_config(c, parent_font));
|
|
}
|
|
|
|
static struct module *
|
|
module_clock_from_config(const struct yml_node *node, const struct font *parent_font)
|
|
{
|
|
const struct yml_node *c = yml_get_value(node, "content");
|
|
assert(c != NULL);
|
|
return module_clock(particle_from_config(c, parent_font));
|
|
}
|
|
|
|
static struct module *
|
|
module_xwindow_from_config(const struct yml_node *node, const struct font *parent_font)
|
|
{
|
|
const struct yml_node *c = yml_get_value(node, "content");
|
|
assert(c != NULL);
|
|
return module_xwindow(particle_from_config(c, parent_font));
|
|
}
|
|
|
|
static struct module *
|
|
module_i3_from_config(const struct yml_node *node, const struct font *parent_font)
|
|
{
|
|
const struct yml_node *c = yml_get_value(node, "content");
|
|
const struct yml_node *spacing = yml_get_value(node, "spacing");
|
|
const struct yml_node *left_spacing = yml_get_value(node, "left_spacing");
|
|
const struct yml_node *right_spacing = yml_get_value(node, "right_spacing");
|
|
|
|
assert(yml_is_dict(c));
|
|
assert(spacing == NULL || yml_is_scalar(spacing));
|
|
assert(left_spacing == NULL || yml_is_scalar(left_spacing));
|
|
assert(right_spacing == NULL || yml_is_scalar(right_spacing));
|
|
|
|
int left = spacing != NULL ? yml_value_as_int(spacing) :
|
|
left_spacing != NULL ? yml_value_as_int(left_spacing) : 0;
|
|
int right = spacing != NULL ? yml_value_as_int(spacing) :
|
|
right_spacing != NULL ? yml_value_as_int(right_spacing) : 0;
|
|
|
|
struct i3_workspaces workspaces[yml_dict_length(c)];
|
|
|
|
size_t idx = 0;
|
|
for (struct yml_dict_iter it = yml_dict_iter(c);
|
|
it.key != NULL;
|
|
yml_dict_next(&it), idx++)
|
|
{
|
|
assert(yml_is_scalar(it.key));
|
|
workspaces[idx].name = yml_value_as_string(it.key);
|
|
workspaces[idx].content = particle_from_config(it.value, parent_font);
|
|
}
|
|
|
|
return module_i3(workspaces, yml_dict_length(c), left, right);
|
|
}
|
|
|
|
static struct module *
|
|
module_battery_from_config(const struct yml_node *node,
|
|
const struct font *parent_font)
|
|
{
|
|
const struct yml_node *c = yml_get_value(node, "content");
|
|
const struct yml_node *name = yml_get_value(node, "name");
|
|
const struct yml_node *poll_interval = yml_get_value(node, "poll_interval");
|
|
|
|
assert(yml_is_dict(c));
|
|
assert(yml_is_scalar(name));
|
|
assert(poll_interval == NULL || yml_is_scalar(poll_interval));
|
|
|
|
return module_battery(
|
|
yml_value_as_string(name),
|
|
particle_from_config(c, parent_font),
|
|
poll_interval != NULL ? yml_value_as_int(poll_interval) : 60);
|
|
}
|
|
|
|
static struct module *
|
|
module_xkb_from_config(const struct yml_node *node,
|
|
const struct font *parent_font)
|
|
{
|
|
const struct yml_node *c = yml_get_value(node, "content");
|
|
assert(yml_is_dict(c));
|
|
|
|
return module_xkb(particle_from_config(c, parent_font));
|
|
}
|
|
|
|
static struct module *
|
|
module_backlight_from_config(const struct yml_node *node,
|
|
const struct font *parent_font)
|
|
{
|
|
const struct yml_node *name = yml_get_value(node, "name");
|
|
const struct yml_node *c = yml_get_value(node, "content");
|
|
|
|
assert(yml_is_scalar(name));
|
|
assert(yml_is_dict(c));
|
|
|
|
return module_backlight(
|
|
yml_value_as_string(name), particle_from_config(c, parent_font));
|
|
}
|
|
|
|
static struct module *
|
|
module_mpd_from_config(const struct yml_node *node,
|
|
const struct font *parent_font)
|
|
{
|
|
const struct yml_node *host = yml_get_value(node, "host");
|
|
const struct yml_node *port = yml_get_value(node, "port");
|
|
const struct yml_node *c = yml_get_value(node, "content");
|
|
|
|
assert(yml_is_scalar(host));
|
|
assert(port == NULL || yml_is_scalar(port));
|
|
assert(yml_is_dict(c));
|
|
|
|
return module_mpd(
|
|
yml_value_as_string(host),
|
|
port != NULL ? yml_value_as_int(port) : 0,
|
|
particle_from_config(c, parent_font));
|
|
}
|
|
|
|
static struct module *
|
|
module_network_from_config(const struct yml_node *node,
|
|
const struct font *parent_font)
|
|
{
|
|
const struct yml_node *name = yml_get_value(node, "name");
|
|
const struct yml_node *content = yml_get_value(node, "content");
|
|
|
|
assert(yml_is_scalar(name));
|
|
|
|
return module_network(
|
|
yml_value_as_string(name), particle_from_config(content, parent_font));
|
|
}
|
|
|
|
static struct module *
|
|
module_removables_from_config(const struct yml_node *node,
|
|
const struct font *parent_font)
|
|
{
|
|
const struct yml_node *content = yml_get_value(node, "content");
|
|
const struct yml_node *spacing = yml_get_value(node, "spacing");
|
|
const struct yml_node *left_spacing = yml_get_value(node, "left_spacing");
|
|
const struct yml_node *right_spacing = yml_get_value(node, "right_spacing");
|
|
|
|
assert(spacing == NULL || yml_is_scalar(spacing));
|
|
assert(left_spacing == NULL || yml_is_scalar(left_spacing));
|
|
assert(right_spacing == NULL || yml_is_scalar(right_spacing));
|
|
|
|
int left = spacing != NULL ? yml_value_as_int(spacing) :
|
|
left_spacing != NULL ? yml_value_as_int(left_spacing) : 0;
|
|
int right = spacing != NULL ? yml_value_as_int(spacing) :
|
|
right_spacing != NULL ? yml_value_as_int(right_spacing) : 0;
|
|
|
|
return module_removables(
|
|
particle_from_config(content, parent_font), left, right);
|
|
}
|
|
|
|
static struct module *
|
|
module_alsa_from_config(const struct yml_node *node,
|
|
const struct font *parent_font)
|
|
{
|
|
const struct yml_node *card = yml_get_value(node, "card");
|
|
const struct yml_node *mixer = yml_get_value(node, "mixer");
|
|
const struct yml_node *content = yml_get_value(node, "content");
|
|
|
|
assert(yml_is_scalar(card));
|
|
assert(yml_is_scalar(mixer));
|
|
assert(content != NULL);
|
|
|
|
return module_alsa(
|
|
yml_value_as_string(card),
|
|
yml_value_as_string(mixer),
|
|
particle_from_config(content, parent_font));
|
|
}
|
|
|
|
struct bar *
|
|
conf_to_bar(const struct yml_node *bar)
|
|
{
|
|
if (!config_verify_bar(bar))
|
|
return NULL;
|
|
|
|
struct bar_config conf = {0};
|
|
|
|
/* Create a default font */
|
|
struct font *font = font_new("sans");
|
|
|
|
const struct yml_node *height = yml_get_value(bar, "height");
|
|
const struct yml_node *location = yml_get_value(bar, "location");
|
|
const struct yml_node *background = yml_get_value(bar, "background");
|
|
const struct yml_node *spacing = yml_get_value(bar, "spacing");
|
|
const struct yml_node *left_spacing = yml_get_value(bar, "left_spacing");
|
|
const struct yml_node *right_spacing = yml_get_value(bar, "right_spacing");
|
|
const struct yml_node *margin = yml_get_value(bar, "margin");
|
|
const struct yml_node *left_margin = yml_get_value(bar, "left_margin");
|
|
const struct yml_node *right_margin = yml_get_value(bar, "right_margin");
|
|
const struct yml_node *border = yml_get_value(bar, "border");
|
|
const struct yml_node *font_node = yml_get_value(bar, "font");
|
|
const struct yml_node *left = yml_get_value(bar, "left");
|
|
const struct yml_node *center = yml_get_value(bar, "center");
|
|
const struct yml_node *right = yml_get_value(bar, "right");
|
|
|
|
if (height != NULL)
|
|
conf.height = yml_value_as_int(height);
|
|
|
|
if (location != NULL) {
|
|
const char *loc = yml_value_as_string(location);
|
|
assert(strcasecmp(loc, "top") == 0 || strcasecmp(loc, "bottom") == 0);
|
|
|
|
if (strcasecmp(loc, "top") == 0)
|
|
conf.location = BAR_TOP;
|
|
else if (strcasecmp(loc, "bottom") == 0)
|
|
conf.location = BAR_BOTTOM;
|
|
else
|
|
assert(false);
|
|
}
|
|
|
|
if (background != NULL)
|
|
conf.background = color_from_hexstr(yml_value_as_string(background));
|
|
|
|
if (spacing != NULL)
|
|
conf.left_spacing = conf.right_spacing = yml_value_as_int(spacing);
|
|
|
|
if (left_spacing != NULL)
|
|
conf.left_spacing = yml_value_as_int(left_spacing);
|
|
|
|
if (right_spacing != NULL)
|
|
conf.right_spacing = yml_value_as_int(right_spacing);
|
|
|
|
if (margin != NULL)
|
|
conf.left_margin = conf.right_margin = yml_value_as_int(margin);
|
|
|
|
if (left_margin != NULL)
|
|
conf.left_margin = yml_value_as_int(left_margin);
|
|
|
|
if (right_margin != NULL)
|
|
conf.right_margin = yml_value_as_int(right_margin);
|
|
|
|
if (border != NULL) {
|
|
assert(yml_is_dict(border));
|
|
|
|
const struct yml_node *width = yml_get_value(border, "width");
|
|
const struct yml_node *color = yml_get_value(border, "color");
|
|
|
|
if (width != NULL)
|
|
conf.border.width = yml_value_as_int(width);
|
|
|
|
if (color != NULL)
|
|
conf.border.color = color_from_hexstr(yml_value_as_string(color));
|
|
}
|
|
|
|
if (font_node != NULL) {
|
|
font_destroy(font);
|
|
font = font_from_config(font_node);
|
|
}
|
|
|
|
for (size_t i = 0; i < 3; i++) {
|
|
const struct yml_node *node = i == 0 ? left : i == 1 ? center : right;
|
|
|
|
if (node != NULL) {
|
|
const size_t count = yml_list_length(node);
|
|
struct module **mods = calloc(count, sizeof(*mods));
|
|
|
|
size_t idx = 0;
|
|
for (struct yml_list_iter it = yml_list_iter(node);
|
|
it.node != NULL;
|
|
yml_list_next(&it), idx++)
|
|
{
|
|
assert(yml_is_dict(it.node));
|
|
assert(yml_dict_length(it.node) == 1);
|
|
|
|
struct yml_dict_iter m = yml_dict_iter(it.node);
|
|
|
|
const char *mod_name = yml_value_as_string(m.key);
|
|
assert(mod_name != NULL);
|
|
|
|
if (strcmp(mod_name, "label") == 0)
|
|
mods[idx] = module_label_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "clock") == 0)
|
|
mods[idx] = module_clock_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "xwindow") == 0)
|
|
mods[idx] = module_xwindow_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "i3") == 0)
|
|
mods[idx] = module_i3_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "battery") == 0)
|
|
mods[idx] = module_battery_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "xkb") == 0)
|
|
mods[idx] = module_xkb_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "backlight") == 0)
|
|
mods[idx] = module_backlight_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "mpd") == 0)
|
|
mods[idx] = module_mpd_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "network") == 0)
|
|
mods[idx] = module_network_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "removables") == 0)
|
|
mods[idx] = module_removables_from_config(m.value, font);
|
|
else if (strcmp(mod_name, "alsa") == 0)
|
|
mods[idx] = module_alsa_from_config(m.value, font);
|
|
else
|
|
assert(false);
|
|
}
|
|
|
|
if (i == 0) {
|
|
conf.left.mods = mods;
|
|
conf.left.count = count;
|
|
} else if (i == 1) {
|
|
conf.center.mods = mods;
|
|
conf.center.count = count;
|
|
} else {
|
|
conf.right.mods = mods;
|
|
conf.right.count = count;
|
|
}
|
|
}
|
|
}
|
|
|
|
struct bar *ret = bar_new(&conf);
|
|
|
|
free(conf.left.mods);
|
|
free(conf.center.mods);
|
|
free(conf.right.mods);
|
|
font_destroy(font);
|
|
|
|
return ret;
|
|
}
|