forked from external/yambar
Merge branch 'particles-as-plugins'
This commit is contained in:
commit
f066ba055e
33 changed files with 468 additions and 397 deletions
|
@ -40,12 +40,6 @@ add_executable(f00bar
|
||||||
decorations/underline.c decorations/underline.h
|
decorations/underline.c decorations/underline.h
|
||||||
|
|
||||||
particles/dynlist.c particles/dynlist.h
|
particles/dynlist.c particles/dynlist.h
|
||||||
particles/empty.c particles/empty.h
|
|
||||||
particles/list.c particles/list.h
|
|
||||||
particles/map.c particles/map.h
|
|
||||||
particles/progress-bar.c particles/progress-bar.h
|
|
||||||
particles/ramp.c particles/ramp.h
|
|
||||||
particles/string.c particles/string.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# TODO: directory global
|
# TODO: directory global
|
||||||
|
@ -78,15 +72,10 @@ target_link_libraries(f00bar
|
||||||
${YAML_LIBRARIES}
|
${YAML_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(module-sdk INTERFACE)
|
|
||||||
target_compile_definitions(module-sdk INTERFACE _GNU_SOURCE)
|
|
||||||
target_compile_options(module-sdk INTERFACE ${CAIRO_CFLAGS_OTHER})
|
|
||||||
target_include_directories(module-sdk INTERFACE ${CAIRO_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(module-sdk INTERFACE ${CMAKE_THREAD_LIBS_INIT})
|
|
||||||
|
|
||||||
set_property(TARGET f00bar PROPERTY INSTALL_RPATH \$ORIGIN/../lib/f00bar)
|
set_property(TARGET f00bar PROPERTY INSTALL_RPATH \$ORIGIN/../lib/f00bar)
|
||||||
set_property(TARGET f00bar PROPERTY BUILD_RPATH \$ORIGIN/modules)
|
set_property(TARGET f00bar PROPERTY BUILD_RPATH "\$ORIGIN/modules;\$ORIGIN/particles")
|
||||||
|
|
||||||
install(TARGETS f00bar DESTINATION bin)
|
install(TARGETS f00bar DESTINATION bin)
|
||||||
|
|
||||||
|
add_subdirectory(particles)
|
||||||
add_subdirectory(modules)
|
add_subdirectory(modules)
|
||||||
|
|
131
config-verify.c
131
config-verify.c
|
@ -158,8 +158,6 @@ conf_verify_font(keychain_t *chain, const struct yml_node *node)
|
||||||
return conf_verify_dict(chain, node, attrs, sizeof(attrs) / sizeof(attrs[0]));
|
return conf_verify_dict(chain, node, attrs, sizeof(attrs) / sizeof(attrs[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool verify_decoration(keychain_t *chain, const struct yml_node *node);
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
verify_decoration_stack(keychain_t *chain, const struct yml_node *node)
|
verify_decoration_stack(keychain_t *chain, const struct yml_node *node)
|
||||||
{
|
{
|
||||||
|
@ -172,15 +170,15 @@ verify_decoration_stack(keychain_t *chain, const struct yml_node *node)
|
||||||
it.node != NULL;
|
it.node != NULL;
|
||||||
yml_list_next(&it))
|
yml_list_next(&it))
|
||||||
{
|
{
|
||||||
if (!verify_decoration(chain, it.node))
|
if (!conf_verify_decoration(chain, it.node))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
verify_decoration(keychain_t *chain, const struct yml_node *node)
|
conf_verify_decoration(keychain_t *chain, const struct yml_node *node)
|
||||||
{
|
{
|
||||||
assert(yml_is_dict(node));
|
assert(yml_is_dict(node));
|
||||||
|
|
||||||
|
@ -243,8 +241,8 @@ verify_decoration(keychain_t *chain, const struct yml_node *node)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
bool
|
||||||
verify_list_items(keychain_t *chain, const struct yml_node *node)
|
conf_verify_particle_list_items(keychain_t *chain, const struct yml_node *node)
|
||||||
{
|
{
|
||||||
assert(yml_is_list(node));
|
assert(yml_is_list(node));
|
||||||
|
|
||||||
|
@ -259,35 +257,6 @@ verify_list_items(keychain_t *chain, const struct yml_node *node)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
verify_map_values(keychain_t *chain, const struct yml_node *node)
|
|
||||||
{
|
|
||||||
if (!yml_is_dict(node)) {
|
|
||||||
LOG_ERR(
|
|
||||||
"%s: must be a dictionary of workspace-name: particle mappings",
|
|
||||||
conf_err_prefix(chain, node));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (struct yml_dict_iter it = yml_dict_iter(node);
|
|
||||||
it.key != NULL;
|
|
||||||
yml_dict_next(&it))
|
|
||||||
{
|
|
||||||
const char *key = yml_value_as_string(it.key);
|
|
||||||
if (key == NULL) {
|
|
||||||
LOG_ERR("%s: key must be a string", conf_err_prefix(chain, it.key));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!conf_verify_particle(chain_push(chain, key), it.value))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
chain_pop(chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
conf_verify_particle_dictionary(keychain_t *chain, const struct yml_node *node)
|
conf_verify_particle_dictionary(keychain_t *chain, const struct yml_node *node)
|
||||||
{
|
{
|
||||||
|
@ -309,99 +278,29 @@ conf_verify_particle_dictionary(keychain_t *chain, const struct yml_node *node)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define COMMON_ATTRS \
|
const struct particle_info *info = plugin_load_particle(particle_name);
|
||||||
{"margin", false, &conf_verify_int}, \
|
if (info == NULL) {
|
||||||
{"left-margin", false, &conf_verify_int}, \
|
LOG_ERR(
|
||||||
{"right-margin", false, &conf_verify_int}, \
|
"%s: invalid particle name: %s",
|
||||||
{"on-click", false, &conf_verify_string},
|
conf_err_prefix(chain, particle), particle_name);
|
||||||
|
|
||||||
static const struct attr_info empty[] = {
|
|
||||||
COMMON_ATTRS
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attr_info list[] = {
|
|
||||||
{"items", true, &verify_list_items},
|
|
||||||
{"spacing", false, &conf_verify_int},
|
|
||||||
{"left-spacing", false, &conf_verify_int},
|
|
||||||
{"right-spacing", false, &conf_verify_int},
|
|
||||||
COMMON_ATTRS
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attr_info map[] = {
|
|
||||||
{"tag", true, &conf_verify_string},
|
|
||||||
{"values", true, &verify_map_values},
|
|
||||||
{"default", false, &conf_verify_particle},
|
|
||||||
COMMON_ATTRS
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attr_info progress_bar[] = {
|
|
||||||
{"tag", true, &conf_verify_string},
|
|
||||||
{"length", true, &conf_verify_int},
|
|
||||||
/* TODO: make these optional? Default to empty */
|
|
||||||
{"start", true, &conf_verify_particle},
|
|
||||||
{"end", true, &conf_verify_particle},
|
|
||||||
{"fill", true, &conf_verify_particle},
|
|
||||||
{"empty", true, &conf_verify_particle},
|
|
||||||
{"indicator", true, &conf_verify_particle},
|
|
||||||
COMMON_ATTRS
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attr_info ramp[] = {
|
|
||||||
{"tag", true, &conf_verify_string},
|
|
||||||
{"items", true, &verify_list_items},
|
|
||||||
COMMON_ATTRS
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct attr_info string[] = {
|
|
||||||
{"text", true, &conf_verify_string},
|
|
||||||
{"max", false, &conf_verify_int},
|
|
||||||
{"font", false, &conf_verify_font},
|
|
||||||
{"foreground", false, &conf_verify_color},
|
|
||||||
{"deco", false, &verify_decoration},
|
|
||||||
COMMON_ATTRS
|
|
||||||
};
|
|
||||||
|
|
||||||
#undef COMMON_ATTRS
|
|
||||||
|
|
||||||
static const struct {
|
|
||||||
const char *name;
|
|
||||||
const struct attr_info *attrs;
|
|
||||||
size_t count;
|
|
||||||
} particles[] = {
|
|
||||||
{"empty", empty, sizeof(empty) / sizeof(empty[0])},
|
|
||||||
{"list", list, sizeof(list) / sizeof(list[0])},
|
|
||||||
{"map", map, sizeof(map) / sizeof(map[0])},
|
|
||||||
{"progress-bar", progress_bar, sizeof(progress_bar) / sizeof(progress_bar[0])},
|
|
||||||
{"ramp", ramp, sizeof(ramp) / sizeof(ramp[0])},
|
|
||||||
{"string", string, sizeof(string) / sizeof(string[0])},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(particles) / sizeof(particles[0]); i++) {
|
|
||||||
if (strcmp(particles[i].name, particle_name) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!conf_verify_dict(chain_push(chain, particle_name), values,
|
|
||||||
particles[i].attrs, particles[i].count))
|
|
||||||
{
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!conf_verify_dict(chain_push(chain, particle_name), values,
|
||||||
|
info->attrs, info->attr_count))
|
||||||
|
return false;
|
||||||
|
|
||||||
chain_pop(chain);
|
chain_pop(chain);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERR(
|
|
||||||
"%s: invalid particle name: %s", conf_err_prefix(chain, particle), particle_name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
conf_verify_particle(keychain_t *chain, const struct yml_node *node)
|
conf_verify_particle(keychain_t *chain, const struct yml_node *node)
|
||||||
{
|
{
|
||||||
if (yml_is_dict(node))
|
if (yml_is_dict(node))
|
||||||
return conf_verify_particle_dictionary(chain, node);
|
return conf_verify_particle_dictionary(chain, node);
|
||||||
else if (yml_is_list(node))
|
else if (yml_is_list(node))
|
||||||
return verify_list_items(chain, node);
|
return conf_verify_particle_list_items(chain, node);
|
||||||
else {
|
else {
|
||||||
LOG_ERR("%s: particle must be either a dictionary or a list",
|
LOG_ERR("%s: particle must be either a dictionary or a list",
|
||||||
conf_err_prefix(chain, node));
|
conf_err_prefix(chain, node));
|
||||||
|
|
|
@ -42,3 +42,6 @@ bool conf_verify_color(keychain_t *chain, const struct yml_node *node);
|
||||||
bool conf_verify_font(keychain_t *chain, const struct yml_node *node);
|
bool conf_verify_font(keychain_t *chain, const struct yml_node *node);
|
||||||
|
|
||||||
bool conf_verify_particle(keychain_t *chain, const struct yml_node *node);
|
bool conf_verify_particle(keychain_t *chain, const struct yml_node *node);
|
||||||
|
bool conf_verify_particle_list_items(keychain_t *chain, const struct yml_node *node);
|
||||||
|
|
||||||
|
bool conf_verify_decoration(keychain_t *chain, const struct yml_node *node);
|
||||||
|
|
215
config.c
215
config.c
|
@ -5,6 +5,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
|
||||||
#include "decoration.h"
|
#include "decoration.h"
|
||||||
|
@ -12,14 +14,6 @@
|
||||||
#include "decorations/stack.h"
|
#include "decorations/stack.h"
|
||||||
#include "decorations/underline.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 "module.h"
|
||||||
#include "config-verify.h"
|
#include "config-verify.h"
|
||||||
#include "plugin.h"
|
#include "plugin.h"
|
||||||
|
@ -47,10 +41,14 @@ hex_byte(const char hex[2])
|
||||||
return upper << 4 | lower;
|
return upper << 4 | lower;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rgba
|
struct rgba
|
||||||
color_from_hexstr(const char *hex)
|
conf_to_color(const struct yml_node *node)
|
||||||
{
|
{
|
||||||
|
const char *hex = yml_value_as_string(node);
|
||||||
|
|
||||||
|
assert(hex != NULL);
|
||||||
assert(strlen(hex) == 8);
|
assert(strlen(hex) == 8);
|
||||||
|
|
||||||
uint8_t red = hex_byte(&hex[0]);
|
uint8_t red = hex_byte(&hex[0]);
|
||||||
uint8_t green = hex_byte(&hex[2]);
|
uint8_t green = hex_byte(&hex[2]);
|
||||||
uint8_t blue = hex_byte(&hex[4]);
|
uint8_t blue = hex_byte(&hex[4]);
|
||||||
|
@ -71,8 +69,8 @@ color_from_hexstr(const char *hex)
|
||||||
return rgba;
|
return rgba;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct font *
|
struct font *
|
||||||
font_from_config(const struct yml_node *node)
|
conf_to_font(const struct yml_node *node)
|
||||||
{
|
{
|
||||||
const struct yml_node *family = yml_get_value(node, "family");
|
const struct yml_node *family = yml_get_value(node, "family");
|
||||||
return font_new(family != NULL ? yml_value_as_string(family) : "monospace");
|
return font_new(family != NULL ? yml_value_as_string(family) : "monospace");
|
||||||
|
@ -82,7 +80,7 @@ static struct deco *
|
||||||
deco_background_from_config(const struct yml_node *node)
|
deco_background_from_config(const struct yml_node *node)
|
||||||
{
|
{
|
||||||
const struct yml_node *color = yml_get_value(node, "color");
|
const struct yml_node *color = yml_get_value(node, "color");
|
||||||
return deco_background(color_from_hexstr(yml_value_as_string(color)));
|
return deco_background(conf_to_color(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct deco *
|
static struct deco *
|
||||||
|
@ -90,10 +88,7 @@ deco_underline_from_config(const struct yml_node *node)
|
||||||
{
|
{
|
||||||
const struct yml_node *size = yml_get_value(node, "size");
|
const struct yml_node *size = yml_get_value(node, "size");
|
||||||
const struct yml_node *color = yml_get_value(node, "color");
|
const struct yml_node *color = yml_get_value(node, "color");
|
||||||
|
return deco_underline(yml_value_as_int(size), conf_to_color(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_from_config(const struct yml_node *node);
|
||||||
|
@ -137,150 +132,6 @@ deco_from_config(const struct yml_node *node)
|
||||||
return NULL;
|
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)
|
|
||||||
{
|
|
||||||
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");
|
|
||||||
|
|
||||||
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_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] = conf_to_particle(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");
|
|
||||||
|
|
||||||
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 = conf_to_particle(it.value, parent_font);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct particle *default_particle = def != NULL
|
|
||||||
? conf_to_particle(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");
|
|
||||||
|
|
||||||
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] = conf_to_particle(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");
|
|
||||||
|
|
||||||
return particle_progress_bar_new(
|
|
||||||
yml_value_as_string(tag),
|
|
||||||
yml_value_as_int(length),
|
|
||||||
conf_to_particle(start, parent_font),
|
|
||||||
conf_to_particle(end, parent_font),
|
|
||||||
conf_to_particle(fill, parent_font),
|
|
||||||
conf_to_particle(empty, parent_font),
|
|
||||||
conf_to_particle(indicator, parent_font),
|
|
||||||
left_margin, right_margin, on_click_template);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct particle *
|
static struct particle *
|
||||||
particle_simple_list_from_config(const struct yml_node *node,
|
particle_simple_list_from_config(const struct yml_node *node,
|
||||||
const struct font *parent_font)
|
const struct font *parent_font)
|
||||||
|
@ -296,6 +147,18 @@ particle_simple_list_from_config(const struct yml_node *node,
|
||||||
parts[idx] = conf_to_particle(it.node, parent_font);
|
parts[idx] = conf_to_particle(it.node, parent_font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Lazy-loaded function pointer to particle_list_new() */
|
||||||
|
static struct particle *(*particle_list_new)(
|
||||||
|
struct particle *particles[], size_t count,
|
||||||
|
int left_spacing, int right_spacing, int left_margin, int right_margin,
|
||||||
|
const char *on_click_template) = NULL;
|
||||||
|
|
||||||
|
if (particle_list_new == NULL) {
|
||||||
|
const struct plugin *plug = plugin_load("list", PLUGIN_PARTICLE);
|
||||||
|
particle_list_new = dlsym(plug->lib, "particle_list_new");
|
||||||
|
assert(particle_list_new != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
return particle_list_new(parts, count, 0, 2, 0, 0, NULL);
|
return particle_list_new(parts, count, 0, 2, 0, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,27 +184,11 @@ conf_to_particle(const struct yml_node *node, const struct font *parent_font)
|
||||||
const char *on_click_template
|
const char *on_click_template
|
||||||
= on_click != NULL ? yml_value_as_string(on_click) : NULL;
|
= on_click != NULL ? yml_value_as_string(on_click) : NULL;
|
||||||
|
|
||||||
struct particle *ret = NULL;
|
const struct particle_info *info = plugin_load_particle(type);
|
||||||
if (strcmp(type, "empty") == 0)
|
assert(info != NULL);
|
||||||
ret = particle_empty_from_config(
|
|
||||||
|
struct particle *ret = info->from_conf(
|
||||||
pair.value, parent_font, left, right, on_click_template);
|
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");
|
const struct yml_node *deco_node = yml_get_value(pair.value, "deco");
|
||||||
|
|
||||||
|
@ -371,7 +218,7 @@ conf_to_bar(const struct yml_node *bar)
|
||||||
? BAR_TOP : BAR_BOTTOM;
|
? BAR_TOP : BAR_BOTTOM;
|
||||||
|
|
||||||
const struct yml_node *background = yml_get_value(bar, "background");
|
const struct yml_node *background = yml_get_value(bar, "background");
|
||||||
conf.background = color_from_hexstr(yml_value_as_string(background));
|
conf.background = conf_to_color(background);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Optional attributes
|
* Optional attributes
|
||||||
|
@ -410,7 +257,7 @@ conf_to_bar(const struct yml_node *bar)
|
||||||
conf.border.width = yml_value_as_int(width);
|
conf.border.width = yml_value_as_int(width);
|
||||||
|
|
||||||
if (color != NULL)
|
if (color != NULL)
|
||||||
conf.border.color = color_from_hexstr(yml_value_as_string(color));
|
conf.border.color = conf_to_color(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a default font */
|
/* Create a default font */
|
||||||
|
@ -419,7 +266,7 @@ conf_to_bar(const struct yml_node *bar)
|
||||||
const struct yml_node *font_node = yml_get_value(bar, "font");
|
const struct yml_node *font_node = yml_get_value(bar, "font");
|
||||||
if (font_node != NULL) {
|
if (font_node != NULL) {
|
||||||
font_destroy(font);
|
font_destroy(font);
|
||||||
font = font_from_config(font_node);
|
font = conf_to_font(font_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct yml_node *left = yml_get_value(bar, "left");
|
const struct yml_node *left = yml_get_value(bar, "left");
|
||||||
|
|
3
config.h
3
config.h
|
@ -12,5 +12,8 @@ struct bar *conf_to_bar(const struct yml_node *bar);
|
||||||
* Utility functions, for e.g. modules
|
* Utility functions, for e.g. modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct rgba conf_to_color(const struct yml_node *node);
|
||||||
|
struct font *conf_to_font(const struct yml_node *node);
|
||||||
|
|
||||||
struct particle * conf_to_particle(
|
struct particle * conf_to_particle(
|
||||||
const struct yml_node *node, const struct font *parent_font);
|
const struct yml_node *node, const struct font *parent_font);
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
add_library(module-sdk INTERFACE)
|
||||||
|
target_compile_definitions(module-sdk INTERFACE _GNU_SOURCE)
|
||||||
|
target_compile_options(module-sdk INTERFACE ${CAIRO_CFLAGS_OTHER})
|
||||||
|
target_include_directories(module-sdk INTERFACE ${CAIRO_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(module-sdk INTERFACE ${CMAKE_THREAD_LIBS_INIT})
|
||||||
|
|
||||||
|
set(CMAKE_SHARED_MODULE_PREFIX module_)
|
||||||
|
|
||||||
pkg_check_modules(ALSA REQUIRED alsa)
|
pkg_check_modules(ALSA REQUIRED alsa)
|
||||||
add_library(alsa MODULE alsa.c)
|
add_library(alsa MODULE alsa.c)
|
||||||
target_compile_options(alsa PRIVATE ${ALSA_CFLAGS_OTHER})
|
target_compile_options(alsa PRIVATE ${ALSA_CFLAGS_OTHER})
|
||||||
|
|
|
@ -280,7 +280,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
conf_to_particle(content, parent_font));
|
conf_to_particle(content, parent_font));
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 4,
|
.attr_count = 4,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -224,7 +224,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
yml_value_as_string(name), conf_to_particle(c, parent_font));
|
yml_value_as_string(name), conf_to_particle(c, parent_font));
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 3,
|
.attr_count = 3,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -356,7 +356,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
poll_interval != NULL ? yml_value_as_int(poll_interval) : 60);
|
poll_interval != NULL ? yml_value_as_int(poll_interval) : 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 4,
|
.attr_count = 4,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -107,7 +107,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
time_format != NULL ? yml_value_as_string(time_format) : "%H:%M");
|
time_format != NULL ? yml_value_as_string(time_format) : "%H:%M");
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 4,
|
.attr_count = 4,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -701,7 +701,7 @@ verify_content(keychain_t *chain, const struct yml_node *node)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 5,
|
.attr_count = 5,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -53,7 +53,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
return label_new(conf_to_particle(c, parent_font));
|
return label_new(conf_to_particle(c, parent_font));
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 2,
|
.attr_count = 2,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -491,7 +491,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
conf_to_particle(c, parent_font));
|
conf_to_particle(c, parent_font));
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 4,
|
.attr_count = 4,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -543,7 +543,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
yml_value_as_string(name), conf_to_particle(content, parent_font));
|
yml_value_as_string(name), conf_to_particle(content, parent_font));
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 3,
|
.attr_count = 3,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -577,7 +577,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
conf_to_particle(content, parent_font), left, right);
|
conf_to_particle(content, parent_font), left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 5,
|
.attr_count = 5,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -459,7 +459,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
return xkb_new(conf_to_particle(c, parent_font));
|
return xkb_new(conf_to_particle(c, parent_font));
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 2,
|
.attr_count = 2,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
|
@ -321,7 +321,7 @@ from_conf(const struct yml_node *node, const struct font *parent_font)
|
||||||
return xwindow_new(conf_to_particle(c, parent_font));
|
return xwindow_new(conf_to_particle(c, parent_font));
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info module_info = {
|
const struct module_info plugin_info = {
|
||||||
.from_conf = &from_conf,
|
.from_conf = &from_conf,
|
||||||
.attr_count = 2,
|
.attr_count = 2,
|
||||||
.attrs = {
|
.attrs = {
|
||||||
|
|
23
particle.h
23
particle.h
|
@ -3,13 +3,36 @@
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
#include "color.h"
|
#include "color.h"
|
||||||
|
#include "config-verify.h"
|
||||||
#include "decoration.h"
|
#include "decoration.h"
|
||||||
#include "font.h"
|
#include "font.h"
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
#include "yml.h"
|
||||||
|
|
||||||
struct bar;
|
struct bar;
|
||||||
|
struct particle;
|
||||||
struct exposable;
|
struct exposable;
|
||||||
|
|
||||||
|
struct particle_info {
|
||||||
|
struct particle *(*from_conf)(const struct yml_node *node,
|
||||||
|
const struct font *parent_font,
|
||||||
|
int left_margin, int right_margin,
|
||||||
|
const char *on_click_template);
|
||||||
|
|
||||||
|
size_t attr_count; /* TODO: reomve, NULL-terminate attr list instead */
|
||||||
|
const struct attr_info attrs[];
|
||||||
|
|
||||||
|
#define PARTICLE_COMMON_ATTRS_COUNT 5
|
||||||
|
#define PARTICLE_COMMON_ATTRS \
|
||||||
|
{"margin", false, &conf_verify_int}, \
|
||||||
|
{"left-margin", false, &conf_verify_int}, \
|
||||||
|
{"right-margin", false, &conf_verify_int}, \
|
||||||
|
{"on-click", false, &conf_verify_string}, \
|
||||||
|
{"deco", false, &conf_verify_decoration}, \
|
||||||
|
{NULL, false, NULL}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
struct particle {
|
struct particle {
|
||||||
void *private;
|
void *private;
|
||||||
|
|
||||||
|
|
37
particles/CMakeLists.txt
Normal file
37
particles/CMakeLists.txt
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
add_library(particle-sdk INTERFACE)
|
||||||
|
target_compile_definitions(particle-sdk INTERFACE _GNU_SOURCE)
|
||||||
|
target_compile_options(particle-sdk INTERFACE ${CAIRO_CFLAGS_OTHER})
|
||||||
|
target_include_directories(particle-sdk INTERFACE ${CAIRO_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
set(CMAKE_SHARED_MODULE_PREFIX particle_)
|
||||||
|
|
||||||
|
add_library(empty MODULE empty.c empty.h)
|
||||||
|
target_link_libraries(empty particle-sdk)
|
||||||
|
|
||||||
|
add_library(list MODULE list.c list.h)
|
||||||
|
target_link_libraries(list particle-sdk)
|
||||||
|
|
||||||
|
add_library(map MODULE map.c map.h)
|
||||||
|
target_link_libraries(map particle-sdk)
|
||||||
|
|
||||||
|
add_library(progress-bar MODULE progress-bar.c progress-bar.h)
|
||||||
|
target_link_libraries(progress-bar particle-sdk)
|
||||||
|
|
||||||
|
add_library(ramp MODULE ramp.c ramp.h)
|
||||||
|
target_link_libraries(ramp particle-sdk)
|
||||||
|
|
||||||
|
add_library(string MODULE string.c string.h)
|
||||||
|
target_link_libraries(string particle-sdk)
|
||||||
|
|
||||||
|
install(
|
||||||
|
TARGETS
|
||||||
|
empty
|
||||||
|
list
|
||||||
|
map
|
||||||
|
progress-bar
|
||||||
|
ramp
|
||||||
|
string
|
||||||
|
|
||||||
|
DESTINATION lib/f00bar)
|
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
static int
|
static int
|
||||||
begin_expose(struct exposable *exposable)
|
begin_expose(struct exposable *exposable)
|
||||||
{
|
{
|
||||||
|
@ -29,9 +31,8 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
return exposable;
|
return exposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct particle *
|
static struct particle *
|
||||||
particle_empty_new(int left_margin, int right_margin,
|
empty_new(int left_margin, int right_margin, const char *on_click_template)
|
||||||
const char *on_click_template)
|
|
||||||
{
|
{
|
||||||
struct particle *particle = particle_common_new(
|
struct particle *particle = particle_common_new(
|
||||||
left_margin, right_margin, on_click_template);
|
left_margin, right_margin, on_click_template);
|
||||||
|
@ -39,3 +40,18 @@ particle_empty_new(int left_margin, int right_margin,
|
||||||
particle->instantiate = &instantiate;
|
particle->instantiate = &instantiate;
|
||||||
return particle;
|
return particle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct particle *
|
||||||
|
from_conf(const struct yml_node *node, const struct font *parent_font,
|
||||||
|
int left_margin, int right_margin, const char *on_click_template)
|
||||||
|
{
|
||||||
|
return empty_new(left_margin, right_margin, on_click_template);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct particle_info plugin_info = {
|
||||||
|
.from_conf = &from_conf,
|
||||||
|
.attr_count = PARTICLE_COMMON_ATTRS_COUNT + 0,
|
||||||
|
.attrs = {
|
||||||
|
PARTICLE_COMMON_ATTRS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../particle.h"
|
#include "../particle.h"
|
||||||
|
|
||||||
struct particle *particle_empty_new(
|
extern const struct particle_info particle_empty;
|
||||||
int left_margin, int right_margin, const char *on_click_template);
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#define LOG_MODULE "list"
|
#define LOG_MODULE "list"
|
||||||
#define LOG_ENABLE_DBG 1
|
#define LOG_ENABLE_DBG 1
|
||||||
#include "../log.h"
|
#include "../log.h"
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
struct private {
|
struct private {
|
||||||
struct particle **particles;
|
struct particle **particles;
|
||||||
|
@ -165,3 +166,46 @@ particle_list_new(
|
||||||
|
|
||||||
return particle;
|
return particle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct particle *
|
||||||
|
from_conf(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] = conf_to_particle(it.node, parent_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
return particle_list_new(
|
||||||
|
parts, count, left_spacing, right_spacing, left_margin, right_margin,
|
||||||
|
on_click_template);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct particle_info plugin_info = {
|
||||||
|
.from_conf = &from_conf,
|
||||||
|
.attr_count = PARTICLE_COMMON_ATTRS_COUNT + 4,
|
||||||
|
.attrs = {
|
||||||
|
{"items", true, &conf_verify_particle_list_items},
|
||||||
|
{"spacing", false, &conf_verify_int},
|
||||||
|
{"left-spacing", false, &conf_verify_int},
|
||||||
|
{"right-spacing", false, &conf_verify_int},
|
||||||
|
PARTICLE_COMMON_ATTRS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -5,3 +5,5 @@ struct particle *particle_list_new(
|
||||||
struct particle *particles[], size_t count,
|
struct particle *particles[], size_t count,
|
||||||
int left_spacing, int right_spacing, int left_margin, int right_margin,
|
int left_spacing, int right_spacing, int left_margin, int right_margin,
|
||||||
const char *on_click_template);
|
const char *on_click_template);
|
||||||
|
|
||||||
|
extern const struct particle_info particle_list;
|
||||||
|
|
|
@ -4,6 +4,15 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#define LOG_MODULE "map"
|
||||||
|
#include "../log.h"
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
|
struct particle_map {
|
||||||
|
const char *tag_value;
|
||||||
|
struct particle *particle;
|
||||||
|
};
|
||||||
|
|
||||||
struct private {
|
struct private {
|
||||||
char *tag;
|
char *tag;
|
||||||
struct particle *default_particle;
|
struct particle *default_particle;
|
||||||
|
@ -136,8 +145,8 @@ particle_destroy(struct particle *particle)
|
||||||
particle_default_destroy(particle);
|
particle_default_destroy(particle);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct particle *
|
static struct particle *
|
||||||
particle_map_new(const char *tag, const struct particle_map *particle_map,
|
map_new(const char *tag, const struct particle_map *particle_map,
|
||||||
size_t count, struct particle *default_particle,
|
size_t count, struct particle *default_particle,
|
||||||
int left_margin, int right_margin,
|
int left_margin, int right_margin,
|
||||||
const char *on_click_template)
|
const char *on_click_template)
|
||||||
|
@ -161,3 +170,71 @@ particle_map_new(const char *tag, const struct particle_map *particle_map,
|
||||||
particle->private = priv;
|
particle->private = priv;
|
||||||
return particle;
|
return particle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
verify_map_values(keychain_t *chain, const struct yml_node *node)
|
||||||
|
{
|
||||||
|
if (!yml_is_dict(node)) {
|
||||||
|
LOG_ERR(
|
||||||
|
"%s: must be a dictionary of workspace-name: particle mappings",
|
||||||
|
conf_err_prefix(chain, node));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (struct yml_dict_iter it = yml_dict_iter(node);
|
||||||
|
it.key != NULL;
|
||||||
|
yml_dict_next(&it))
|
||||||
|
{
|
||||||
|
const char *key = yml_value_as_string(it.key);
|
||||||
|
if (key == NULL) {
|
||||||
|
LOG_ERR("%s: key must be a string", conf_err_prefix(chain, it.key));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!conf_verify_particle(chain_push(chain, key), it.value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
chain_pop(chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct particle *
|
||||||
|
from_conf(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");
|
||||||
|
|
||||||
|
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 = conf_to_particle(it.value, parent_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct particle *default_particle = def != NULL
|
||||||
|
? conf_to_particle(def, parent_font)
|
||||||
|
: NULL;
|
||||||
|
|
||||||
|
return map_new(
|
||||||
|
yml_value_as_string(tag), particle_map, yml_dict_length(values),
|
||||||
|
default_particle, left_margin, right_margin, on_click_template);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct particle_info plugin_info = {
|
||||||
|
.from_conf = &from_conf,
|
||||||
|
.attr_count = PARTICLE_COMMON_ATTRS_COUNT + 3,
|
||||||
|
.attrs = {
|
||||||
|
{"tag", true, &conf_verify_string},
|
||||||
|
{"values", true, &verify_map_values},
|
||||||
|
{"default", false, &conf_verify_particle},
|
||||||
|
PARTICLE_COMMON_ATTRS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -1,12 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../particle.h"
|
#include "../particle.h"
|
||||||
|
|
||||||
struct particle_map {
|
extern const struct particle_info particle_map;
|
||||||
const char *tag_value;
|
|
||||||
struct particle *particle;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct particle *particle_map_new(
|
|
||||||
const char *tag, const struct particle_map *particle_map, size_t count,
|
|
||||||
struct particle *default_particle, int left_margin, int right_margin,
|
|
||||||
const char *on_click_template);
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#define LOG_MODULE "progress_bar"
|
#define LOG_MODULE "progress_bar"
|
||||||
#define LOG_ENABLE_DBG 0
|
#define LOG_ENABLE_DBG 0
|
||||||
#include "../log.h"
|
#include "../log.h"
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
struct private {
|
struct private {
|
||||||
char *tag;
|
char *tag;
|
||||||
|
@ -206,8 +207,8 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
return exposable;
|
return exposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct particle *
|
static struct particle *
|
||||||
particle_progress_bar_new(const char *tag, int width,
|
progress_bar_new(const char *tag, int width,
|
||||||
struct particle *start_marker,
|
struct particle *start_marker,
|
||||||
struct particle *end_marker,
|
struct particle *end_marker,
|
||||||
struct particle *fill, struct particle *empty,
|
struct particle *fill, struct particle *empty,
|
||||||
|
@ -232,3 +233,42 @@ particle_progress_bar_new(const char *tag, int width,
|
||||||
|
|
||||||
return particle;
|
return particle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct particle *
|
||||||
|
from_conf(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");
|
||||||
|
|
||||||
|
return progress_bar_new(
|
||||||
|
yml_value_as_string(tag),
|
||||||
|
yml_value_as_int(length),
|
||||||
|
conf_to_particle(start, parent_font),
|
||||||
|
conf_to_particle(end, parent_font),
|
||||||
|
conf_to_particle(fill, parent_font),
|
||||||
|
conf_to_particle(empty, parent_font),
|
||||||
|
conf_to_particle(indicator, parent_font),
|
||||||
|
left_margin, right_margin, on_click_template);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct particle_info plugin_info = {
|
||||||
|
.from_conf = &from_conf,
|
||||||
|
.attr_count = PARTICLE_COMMON_ATTRS_COUNT + 7,
|
||||||
|
.attrs = {
|
||||||
|
{"tag", true, &conf_verify_string},
|
||||||
|
{"length", true, &conf_verify_int},
|
||||||
|
/* TODO: make these optional? Default to empty */
|
||||||
|
{"start", true, &conf_verify_particle},
|
||||||
|
{"end", true, &conf_verify_particle},
|
||||||
|
{"fill", true, &conf_verify_particle},
|
||||||
|
{"empty", true, &conf_verify_particle},
|
||||||
|
{"indicator", true, &conf_verify_particle},
|
||||||
|
PARTICLE_COMMON_ATTRS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../particle.h"
|
#include "../particle.h"
|
||||||
|
|
||||||
struct particle * particle_progress_bar_new(
|
extern const struct particle_info particle_progress_bar;
|
||||||
const char *tag, int width,
|
|
||||||
struct particle *start_marker, struct particle *end_marker,
|
|
||||||
struct particle *fill, struct particle *empty, struct particle *indicator,
|
|
||||||
int left_margin, int right_margin, const char *on_click_template);
|
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
struct private {
|
struct private {
|
||||||
char *tag;
|
char *tag;
|
||||||
struct particle **particles;
|
struct particle **particles;
|
||||||
|
@ -132,10 +134,9 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
|
||||||
return exposable;
|
return exposable;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct particle *
|
static struct particle *
|
||||||
particle_ramp_new(const char *tag, struct particle *particles[], size_t count,
|
ramp_new(const char *tag, struct particle *particles[], size_t count,
|
||||||
int left_margin, int right_margin,
|
int left_margin, int right_margin, const char *on_click_template)
|
||||||
const char *on_click_template)
|
|
||||||
{
|
{
|
||||||
struct particle *particle = particle_common_new(
|
struct particle *particle = particle_common_new(
|
||||||
left_margin, right_margin, on_click_template);
|
left_margin, right_margin, on_click_template);
|
||||||
|
@ -153,3 +154,36 @@ particle_ramp_new(const char *tag, struct particle *particles[], size_t count,
|
||||||
particle->private = priv;
|
particle->private = priv;
|
||||||
return particle;
|
return particle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct particle *
|
||||||
|
from_conf(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");
|
||||||
|
|
||||||
|
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] = conf_to_particle(it.node, parent_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ramp_new(
|
||||||
|
yml_value_as_string(tag), parts, count, left_margin, right_margin,
|
||||||
|
on_click_template);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct particle_info plugin_info = {
|
||||||
|
.from_conf = &from_conf,
|
||||||
|
.attr_count = PARTICLE_COMMON_ATTRS_COUNT + 2,
|
||||||
|
.attrs = {
|
||||||
|
{"tag", true, &conf_verify_string},
|
||||||
|
{"items", true, &conf_verify_particle_list_items},
|
||||||
|
PARTICLE_COMMON_ATTRS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../particle.h"
|
#include "../particle.h"
|
||||||
|
|
||||||
struct particle *particle_ramp_new(
|
extern const struct particle_info particle_ramp;
|
||||||
const char *tag, struct particle *particles[], size_t count,
|
|
||||||
int left_margin, int right_margin, const char *on_click_template);
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#define LOG_MODULE "string"
|
#define LOG_MODULE "string"
|
||||||
#define LOG_ENABLE_DBG 1
|
#define LOG_ENABLE_DBG 1
|
||||||
#include "../log.h"
|
#include "../log.h"
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
struct private {
|
struct private {
|
||||||
char *text;
|
char *text;
|
||||||
|
@ -130,8 +131,8 @@ particle_destroy(struct particle *particle)
|
||||||
particle_default_destroy(particle);
|
particle_default_destroy(particle);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct particle *
|
static struct particle *
|
||||||
particle_string_new(const char *text, size_t max_len, struct font *font,
|
string_new(const char *text, size_t max_len, struct font *font,
|
||||||
struct rgba foreground, int left_margin, int right_margin,
|
struct rgba foreground, int left_margin, int right_margin,
|
||||||
const char *on_click_template)
|
const char *on_click_template)
|
||||||
{
|
{
|
||||||
|
@ -150,3 +151,34 @@ particle_string_new(const char *text, size_t max_len, struct font *font,
|
||||||
|
|
||||||
return particle;
|
return particle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct particle *
|
||||||
|
from_conf(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 *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");
|
||||||
|
|
||||||
|
struct rgba fg_color = foreground != NULL
|
||||||
|
? conf_to_color(foreground) : (struct rgba){1.0, 1.0, 1.0, 1.0};
|
||||||
|
|
||||||
|
return string_new(
|
||||||
|
yml_value_as_string(text),
|
||||||
|
max != NULL ? yml_value_as_int(max) : 0,
|
||||||
|
font != NULL ? conf_to_font(font) : font_clone(parent_font),
|
||||||
|
fg_color, left_margin, right_margin, on_click_template);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct particle_info plugin_info = {
|
||||||
|
.from_conf = &from_conf,
|
||||||
|
.attr_count = PARTICLE_COMMON_ATTRS_COUNT + 4,
|
||||||
|
.attrs = {
|
||||||
|
{"text", true, &conf_verify_string},
|
||||||
|
{"max", false, &conf_verify_int},
|
||||||
|
{"font", false, &conf_verify_font},
|
||||||
|
{"foreground", false, &conf_verify_color},
|
||||||
|
PARTICLE_COMMON_ATTRS,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -1,6 +1,4 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "../particle.h"
|
#include "../particle.h"
|
||||||
|
|
||||||
struct particle *particle_string_new(
|
extern const struct particle_info particle_string;
|
||||||
const char *text, size_t max_len, struct font *font, struct rgba foreground,
|
|
||||||
int left_margin, int right_margin, const char *on_click_template);
|
|
||||||
|
|
66
plugin.c
66
plugin.c
|
@ -9,14 +9,19 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "tllist.h"
|
#include "tllist.h"
|
||||||
|
|
||||||
struct plugin {
|
|
||||||
char *name;
|
|
||||||
void *lib;
|
|
||||||
const void *sym;
|
|
||||||
};
|
|
||||||
|
|
||||||
static tll(struct plugin) plugins = tll_init();
|
static tll(struct plugin) plugins = tll_init();
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
type2str(enum plugin_type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case PLUGIN_MODULE: return "module";
|
||||||
|
case PLUGIN_PARTICLE: return "particle";
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_plugin(struct plugin plug)
|
free_plugin(struct plugin plug)
|
||||||
{
|
{
|
||||||
|
@ -25,7 +30,7 @@ free_plugin(struct plugin plug)
|
||||||
|
|
||||||
const char *dl_error = dlerror();
|
const char *dl_error = dlerror();
|
||||||
if (dl_error != NULL)
|
if (dl_error != NULL)
|
||||||
LOG_ERR("%s: dlclose(): %s", plug.name, dl_error);
|
LOG_ERR("%s: %s: dlclose(): %s", type2str(plug.type), plug.name, dl_error);
|
||||||
|
|
||||||
free(plug.name);
|
free(plug.name);
|
||||||
}
|
}
|
||||||
|
@ -36,42 +41,57 @@ fini(void)
|
||||||
tll_free_and_free(plugins, free_plugin);
|
tll_free_and_free(plugins, free_plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct module_info *
|
const struct plugin *
|
||||||
plugin_load_module(const char *name)
|
plugin_load(const char *name, enum plugin_type type)
|
||||||
{
|
{
|
||||||
char path[128];
|
|
||||||
snprintf(path, sizeof(path), "lib%s.so", name);
|
|
||||||
|
|
||||||
/* Have we already loaded it? */
|
|
||||||
tll_foreach(plugins, plug) {
|
tll_foreach(plugins, plug) {
|
||||||
if (strcmp(plug->item.name, name) == 0) {
|
if (plug->item.type == type && strcmp(plug->item.name, name) == 0) {
|
||||||
LOG_DBG("%s already loaded: %p", name, plug->item.lib);
|
LOG_DBG("%s: %s already loaded: %p", type2str(type), name, plug->item.lib);
|
||||||
assert(plug->item.sym != NULL);
|
assert(plug->item.sym != NULL);
|
||||||
return plug->item.sym;
|
return &plug->item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char path[128];
|
||||||
|
snprintf(
|
||||||
|
path, sizeof(path), "%s_%s.so",
|
||||||
|
type == PLUGIN_MODULE ? "module" : "particle", name);
|
||||||
|
|
||||||
/* Not loaded - do it now */
|
/* Not loaded - do it now */
|
||||||
void *lib = dlopen(path, RTLD_LOCAL | RTLD_NOW);
|
void *lib = dlopen(path, RTLD_LOCAL | RTLD_NOW);
|
||||||
LOG_DBG("%s: dlopened to %p", name, lib);
|
LOG_DBG("%s: %s: dlopened to %p", type2str(type), name, lib);
|
||||||
|
|
||||||
if (lib == NULL) {
|
if (lib == NULL) {
|
||||||
LOG_ERR("%s: dlopen: %s", name, dlerror());
|
LOG_ERR("%s: %s: dlopen: %s", type2str(type), name, dlerror());
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
tll_push_back(plugins, ((struct plugin){strdup(name), lib}));
|
tll_push_back(plugins, ((struct plugin){strdup(name), type, lib, NULL}));
|
||||||
struct plugin *plug = &tll_back(plugins);
|
struct plugin *plug = &tll_back(plugins);
|
||||||
|
|
||||||
|
/* TODO: rename to plugin_info or so, in both modules and particles */
|
||||||
dlerror(); /* Clear previous error */
|
dlerror(); /* Clear previous error */
|
||||||
plug->sym = dlsym(lib, "module_info");
|
plug->sym = dlsym(lib, "plugin_info");
|
||||||
|
|
||||||
const char *dlsym_error = dlerror();
|
const char *dlsym_error = dlerror();
|
||||||
if (dlsym_error != NULL) {
|
if (dlsym_error != NULL) {
|
||||||
LOG_ERR("%s: dlsym: %s", name, dlsym_error);
|
LOG_ERR("%s: %s: dlsym: %s", type2str(type), name, dlsym_error);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(plug->sym != NULL);
|
return plug;
|
||||||
return plug->sym;
|
}
|
||||||
|
|
||||||
|
const struct module_info *
|
||||||
|
plugin_load_module(const char *name)
|
||||||
|
{
|
||||||
|
const struct plugin *plug = plugin_load(name, PLUGIN_MODULE);
|
||||||
|
return plug != NULL ? plug->sym : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct particle_info *
|
||||||
|
plugin_load_particle(const char *name)
|
||||||
|
{
|
||||||
|
const struct plugin *plug = plugin_load(name, PLUGIN_PARTICLE);
|
||||||
|
return plug != NULL ? plug->sym : NULL;
|
||||||
}
|
}
|
||||||
|
|
14
plugin.h
14
plugin.h
|
@ -1,5 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "module.h"
|
#include "module.h"
|
||||||
|
#include "particle.h"
|
||||||
|
|
||||||
const struct module_info *plugin_load_module(const char *name);
|
const struct module_info *plugin_load_module(const char *name);
|
||||||
|
const struct particle_info *plugin_load_particle(const char *name);
|
||||||
|
|
||||||
|
enum plugin_type { PLUGIN_MODULE, PLUGIN_PARTICLE };
|
||||||
|
|
||||||
|
struct plugin {
|
||||||
|
char *name;
|
||||||
|
enum plugin_type type;
|
||||||
|
|
||||||
|
void *lib;
|
||||||
|
const void *sym;
|
||||||
|
};
|
||||||
|
|
||||||
|
const struct plugin *plugin_load(const char *name, enum plugin_type type);
|
||||||
|
|
Loading…
Add table
Reference in a new issue