diff --git a/CMakeLists.txt b/CMakeLists.txt index e18de16..4c39e6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,10 +35,6 @@ add_executable(f00bar xcb.c xcb.h yml.c yml.h - decorations/background.c decorations/background.h - decorations/stack.c decorations/stack.h - decorations/underline.c decorations/underline.h - particles/dynlist.c particles/dynlist.h ) @@ -70,9 +66,11 @@ target_link_libraries(f00bar ) set_property(TARGET f00bar PROPERTY INSTALL_RPATH \$ORIGIN/../lib/f00bar) -set_property(TARGET f00bar PROPERTY BUILD_RPATH "\$ORIGIN/modules;\$ORIGIN/particles") +set_property(TARGET f00bar PROPERTY + BUILD_RPATH "\$ORIGIN/modules;\$ORIGIN/particles;\$ORIGIN/decorations") install(TARGETS f00bar DESTINATION bin) -add_subdirectory(particles) add_subdirectory(modules) +add_subdirectory(particles) +add_subdirectory(decorations) diff --git a/config-verify.c b/config-verify.c index 3ab76f9..f5bb00d 100644 --- a/config-verify.c +++ b/config-verify.c @@ -164,25 +164,6 @@ conf_verify_font(keychain_t *chain, const struct yml_node *node) return conf_verify_dict(chain, node, attrs); } -static bool -verify_decoration_stack(keychain_t *chain, const struct yml_node *node) -{ - if (!yml_is_list(node)) { - LOG_ERR("%s: must be a list of decorations", conf_err_prefix(chain, node)); - return false; - } - - for (struct yml_list_iter it = yml_list_iter(node); - it.node != NULL; - yml_list_next(&it)) - { - if (!conf_verify_decoration(chain, it.node)) - return false; - } - - return true; -} - bool conf_verify_decoration(keychain_t *chain, const struct yml_node *node) { @@ -204,47 +185,19 @@ conf_verify_decoration(keychain_t *chain, const struct yml_node *node) return false; } - if (strcmp(deco_name, "stack") == 0) { - bool ret = verify_decoration_stack(chain_push(chain, deco_name), values); - chain_pop(chain); - return ret; + const struct deco_iface *iface = plugin_load_deco(deco_name); + if (iface == NULL) { + LOG_ERR("%s: invalid decoration name: %s", + conf_err_prefix(chain, deco), deco_name); + return false; } - static const struct attr_info background[] = { - {"color", true, &conf_verify_color}, - {NULL, false, NULL}, - }; + chain_push(chain, deco_name); + if (!iface->verify_conf(chain, values)) + return false; - static const struct attr_info underline[] = { - {"size", true, &conf_verify_int}, - {"color", true, &conf_verify_color}, - {NULL, false, NULL}, - }; - - static const struct { - const char *name; - const struct attr_info *attrs; - size_t count; - } decos[] = { - {"background", background, sizeof(background) / sizeof(background[0])}, - {"underline", underline, sizeof(underline) / sizeof(underline[0])}, - }; - - for (size_t i = 0; i < sizeof(decos) / sizeof(decos[0]); i++) { - if (strcmp(decos[i].name, deco_name) != 0) - continue; - - chain_push(chain, deco_name); - if (!conf_verify_dict(chain, values, decos[i].attrs)) - return false; - - chain_pop(chain); - return true; - } - - LOG_ERR( - "%s: invalid decoration name: %s", conf_err_prefix(chain, deco), deco_name); - return false; + chain_pop(chain); + return true; } bool diff --git a/config.c b/config.c index 505cb45..63b4809 100644 --- a/config.c +++ b/config.c @@ -7,16 +7,10 @@ #include -#include "color.h" - -#include "decoration.h" -#include "decorations/background.h" -#include "decorations/stack.h" -#include "decorations/underline.h" - #include "bar.h" -#include "module.h" +#include "color.h" #include "config-verify.h" +#include "module.h" #include "plugin.h" static uint8_t @@ -77,60 +71,18 @@ conf_to_font(const struct yml_node *node) return font_new(family != NULL ? yml_value_as_string(family) : "monospace"); } -static struct deco * -deco_background_from_config(const struct yml_node *node) -{ - const struct yml_node *color = yml_get_value(node, "color"); - return deco_background(conf_to_color(color)); -} - -static struct deco * -deco_underline_from_config(const struct yml_node *node) -{ - const struct yml_node *size = yml_get_value(node, "size"); - const struct yml_node *color = yml_get_value(node, "color"); - return deco_underline(yml_value_as_int(size), conf_to_color(color)); -} - -static struct deco *deco_from_config(const struct yml_node *node); - -static struct deco * -deco_stack_from_config(const struct yml_node *node) -{ - size_t count = yml_list_length(node); - - 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) +struct deco * +conf_to_deco(const struct yml_node *node) { 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; const char *type = yml_value_as_string(deco_type); + const struct deco_iface *iface = plugin_load_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; + assert(iface != NULL); + return iface->from_conf(deco_data); } static struct particle * @@ -191,7 +143,7 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited) const char *on_click_template = on_click != NULL ? yml_value_as_string(on_click) : NULL; - struct deco *deco = deco_node != NULL ? deco_from_config(deco_node) : NULL; + struct deco *deco = deco_node != NULL ? conf_to_deco(deco_node) : NULL; /* * Font and foreground are inheritable attributes. Each particle diff --git a/config.h b/config.h index 3579877..ee3f281 100644 --- a/config.h +++ b/config.h @@ -21,5 +21,6 @@ struct conf_inherit { struct rgba foreground; }; -struct particle * conf_to_particle( +struct particle *conf_to_particle( const struct yml_node *node, struct conf_inherit inherited); +struct deco *conf_to_deco(const struct yml_node *node); diff --git a/decoration.h b/decoration.h index b40602c..78f2f05 100644 --- a/decoration.h +++ b/decoration.h @@ -8,3 +8,6 @@ struct deco { int x, int y, int width, int height); void (*destroy)(struct deco *deco); }; + +#define DECORATION_COMMON_ATTRS \ + {NULL, false, NULL} diff --git a/decorations/CMakeLists.txt b/decorations/CMakeLists.txt new file mode 100644 index 0000000..dd06e9d --- /dev/null +++ b/decorations/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.13) + +add_library(decoration-sdk INTERFACE) +target_compile_options(decoration-sdk INTERFACE ${CAIRO_CFLAGS_OTHER}) +target_include_directories(decoration-sdk INTERFACE ${CAIRO_INCLUDE_DIRS}) + +set(CMAKE_SHARED_MODULE_PREFIX decoration_) + +add_library(background MODULE background.c) +target_link_libraries(background decoration-sdk) + +add_library(stack MODULE stack.c) +target_link_libraries(stack decoration-sdk) + +add_library(underline MODULE underline.c) +target_link_libraries(underline decoration-sdk) + +install( + TARGETS + background + stack + underline + + DESTINATION lib/f00bar) diff --git a/decorations/background.c b/decorations/background.c index b0a15a6..0a0c218 100644 --- a/decorations/background.c +++ b/decorations/background.c @@ -1,7 +1,9 @@ -#include "background.h" - #include +#include "../config.h" +#include "../config-verify.h" +#include "../decoration.h" + struct private { struct rgba color; }; @@ -24,8 +26,8 @@ expose(const struct deco *deco, cairo_t *cr, int x, int y, int width, int height cairo_fill(cr); } -struct deco * -deco_background(struct rgba color) +static struct deco * +background_new(struct rgba color) { struct private *priv = malloc(sizeof(*priv)); priv->color = color; @@ -37,3 +39,21 @@ deco_background(struct rgba color) return deco; } + +struct deco * +from_conf(const struct yml_node *node) +{ + const struct yml_node *color = yml_get_value(node, "color"); + return background_new(conf_to_color(color)); +} + +bool +verify_conf(keychain_t *chain, const struct yml_node *node) +{ + static const struct attr_info attrs[] = { + {"color", true, &conf_verify_color}, + DECORATION_COMMON_ATTRS, + }; + + return conf_verify_dict(chain, node, attrs); +} diff --git a/decorations/background.h b/decorations/background.h deleted file mode 100644 index b926e2f..0000000 --- a/decorations/background.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "../color.h" -#include "../decoration.h" - -struct deco *deco_background(struct rgba color); diff --git a/decorations/stack.c b/decorations/stack.c index d7410e4..38d3a74 100644 --- a/decorations/stack.c +++ b/decorations/stack.c @@ -1,7 +1,11 @@ -#include "underline.h" - #include +#define LOG_MODULE "stack" +#include "../log.h" +#include "../config.h" +#include "../config-verify.h" +#include "../decoration.h" + struct private { struct deco **decos; size_t count; @@ -26,8 +30,8 @@ expose(const struct deco *deco, cairo_t *cr, int x, int y, int width, int height d->decos[i]->expose(d->decos[i], cr, x, y, width, height); } -struct deco * -deco_stack(struct deco *decos[], size_t count) +static struct deco * +stack_new(struct deco *decos[], size_t count) { struct private *priv = malloc(sizeof(*priv)); priv->decos = malloc(count * sizeof(priv->decos[0])); @@ -43,3 +47,39 @@ deco_stack(struct deco *decos[], size_t count) return deco; } +struct deco * +from_conf(const struct yml_node *node) +{ + size_t count = yml_list_length(node); + + 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] = conf_to_deco(it.node); + } + + return stack_new(decos, count); +} + +bool +verify_conf(keychain_t *chain, const struct yml_node *node) +{ + if (!yml_is_list(node)) { + LOG_ERR("%s: must be a list of decorations", conf_err_prefix(chain, node)); + return false; + } + + for (struct yml_list_iter it = yml_list_iter(node); + it.node != NULL; + yml_list_next(&it)) + { + if (!conf_verify_decoration(chain, it.node)) + return false; + } + + return true; +} diff --git a/decorations/stack.h b/decorations/stack.h deleted file mode 100644 index ab0380a..0000000 --- a/decorations/stack.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "../color.h" -#include "../decoration.h" - -struct deco *deco_stack(struct deco *decos[], size_t count); diff --git a/decorations/underline.c b/decorations/underline.c index 0b7ce27..838f9a0 100644 --- a/decorations/underline.c +++ b/decorations/underline.c @@ -1,7 +1,9 @@ -#include "underline.h" - #include +#include "../config.h" +#include "../config-verify.h" +#include "../decoration.h" + struct private { int size; struct rgba color; @@ -25,8 +27,8 @@ expose(const struct deco *deco, cairo_t *cr, int x, int y, int width, int height cairo_fill(cr); } -struct deco * -deco_underline(int size, struct rgba color) +static struct deco * +underline_new(int size, struct rgba color) { struct private *priv = malloc(sizeof(*priv)); priv->size = size; @@ -39,3 +41,23 @@ deco_underline(int size, struct rgba color) return deco; } + +struct deco * +from_conf(const struct yml_node *node) +{ + const struct yml_node *size = yml_get_value(node, "size"); + const struct yml_node *color = yml_get_value(node, "color"); + return underline_new(yml_value_as_int(size), conf_to_color(color)); +} + +bool +verify_conf(keychain_t *chain, const struct yml_node *node) +{ + static const struct attr_info attrs[] = { + {"size", true, &conf_verify_int}, + {"color", true, &conf_verify_color}, + DECORATION_COMMON_ATTRS, + }; + + return conf_verify_dict(chain, node, attrs); +} diff --git a/decorations/underline.h b/decorations/underline.h deleted file mode 100644 index 7b69ef6..0000000 --- a/decorations/underline.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -#include "../color.h" -#include "../decoration.h" - -struct deco *deco_underline(int size, struct rgba color); diff --git a/modules/alsa.c b/modules/alsa.c index 3ba2892..be6d876 100644 --- a/modules/alsa.c +++ b/modules/alsa.c @@ -8,6 +8,7 @@ #include "../log.h" #include "../bar.h" #include "../config.h" +#include "../config-verify.h" #include "../tllist.h" struct private { diff --git a/modules/backlight.c b/modules/backlight.c index 6f9bf46..dee1cc0 100644 --- a/modules/backlight.c +++ b/modules/backlight.c @@ -14,6 +14,7 @@ #include "../log.h" #include "../bar.h" #include "../config.h" +#include "../config-verify.h" struct private { struct particle *label; @@ -41,11 +42,15 @@ content(struct module *mod) const struct private *m = mod->private; mtx_lock(&mod->lock); + + const long current = m->current_brightness; + const long max = m->max_brightness; + const long percent = max > 0 ? 100 * current / max : 0; + struct tag_set tags = { .tags = (struct tag *[]){ - tag_new_int_range( - mod, "brightness", m->current_brightness, 0, m->max_brightness), - tag_new_int_range(mod, "percent", 100 * m->current_brightness / m->max_brightness, 0, 100), + tag_new_int_range(mod, "brightness", current, 0, max), + tag_new_int_range(mod, "percent", percent, 0, 100), }, .count = 2, }; diff --git a/modules/battery.c b/modules/battery.c index 303c80b..2fef9d1 100644 --- a/modules/battery.c +++ b/modules/battery.c @@ -15,6 +15,7 @@ #include "../log.h" #include "../bar.h" #include "../config.h" +#include "../config-verify.h" enum state { STATE_FULL, STATE_CHARGING, STATE_DISCHARGING }; diff --git a/modules/clock.c b/modules/clock.c index f87995b..e982907 100644 --- a/modules/clock.c +++ b/modules/clock.c @@ -7,6 +7,7 @@ #include "../bar.h" #include "../config.h" +#include "../config-verify.h" struct private { struct particle *label; diff --git a/modules/i3.c b/modules/i3.c index b48772a..e079429 100644 --- a/modules/i3.c +++ b/modules/i3.c @@ -20,6 +20,7 @@ #include "../log.h" #include "../bar.h" #include "../config.h" +#include "../config-verify.h" #include "../particles/dynlist.h" diff --git a/modules/label.c b/modules/label.c index fb0857d..73d10f5 100644 --- a/modules/label.c +++ b/modules/label.c @@ -4,6 +4,7 @@ #include #include "../config.h" +#include "../config-verify.h" #include "../module.h" struct private { diff --git a/modules/mpd.c b/modules/mpd.c index fae5c35..b4e31b4 100644 --- a/modules/mpd.c +++ b/modules/mpd.c @@ -17,6 +17,7 @@ #include "../log.h" #include "../bar.h" #include "../config.h" +#include "../config-verify.h" enum state { STATE_OFFLINE = 1000, diff --git a/modules/network.c b/modules/network.c index 42a087f..09c0cf4 100644 --- a/modules/network.c +++ b/modules/network.c @@ -17,6 +17,7 @@ #include "../log.h" #include "../bar.h" #include "../config.h" +#include "../config-verify.h" #include "../module.h" #include "../tllist.h" diff --git a/modules/removables.c b/modules/removables.c index b56467e..1b24a6c 100644 --- a/modules/removables.c +++ b/modules/removables.c @@ -17,6 +17,7 @@ #include "../log.h" #include "../bar.h" #include "../config.h" +#include "../config-verify.h" #include "../particles/dynlist.h" #include "../tllist.h" diff --git a/modules/xkb.c b/modules/xkb.c index 9cb422c..8f9ad83 100644 --- a/modules/xkb.c +++ b/modules/xkb.c @@ -12,6 +12,7 @@ #include "../log.h" #include "../bar.h" #include "../config.h" +#include "../config-verify.h" #include "../xcb.h" struct layout { diff --git a/modules/xwindow.c b/modules/xwindow.c index 8fcef32..67e36d5 100644 --- a/modules/xwindow.c +++ b/modules/xwindow.c @@ -16,6 +16,7 @@ #include "../log.h" #include "../bar.h" #include "../config.h" +#include "../config-verify.h" #include "../xcb.h" struct private { diff --git a/particle.h b/particle.h index db552d1..ed569d1 100644 --- a/particle.h +++ b/particle.h @@ -2,7 +2,6 @@ #include #include "color.h" -#include "config-verify.h" #include "decoration.h" #include "font.h" #include "tag.h" diff --git a/particles/CMakeLists.txt b/particles/CMakeLists.txt index c66fc55..f588b8b 100644 --- a/particles/CMakeLists.txt +++ b/particles/CMakeLists.txt @@ -6,22 +6,22 @@ target_include_directories(particle-sdk INTERFACE ${CAIRO_INCLUDE_DIRS}) set(CMAKE_SHARED_MODULE_PREFIX particle_) -add_library(empty MODULE empty.c empty.h) +add_library(empty MODULE empty.c) target_link_libraries(empty particle-sdk) -add_library(list MODULE list.c list.h) +add_library(list MODULE list.c) target_link_libraries(list particle-sdk) -add_library(map MODULE map.c map.h) +add_library(map MODULE map.c) target_link_libraries(map particle-sdk) -add_library(progress-bar MODULE progress-bar.c progress-bar.h) +add_library(progress-bar MODULE progress-bar.c) target_link_libraries(progress-bar particle-sdk) -add_library(ramp MODULE ramp.c ramp.h) +add_library(ramp MODULE ramp.c) target_link_libraries(ramp particle-sdk) -add_library(string MODULE string.c string.h) +add_library(string MODULE string.c) target_link_libraries(string particle-sdk) install( diff --git a/particles/empty.c b/particles/empty.c index 8ed3813..d8b4df4 100644 --- a/particles/empty.c +++ b/particles/empty.c @@ -1,6 +1,7 @@ #include #include "../config.h" +#include "../config-verify.h" #include "../particle.h" static int diff --git a/particles/list.c b/particles/list.c index 3ee6abb..43f3874 100644 --- a/particles/list.c +++ b/particles/list.c @@ -4,6 +4,7 @@ #define LOG_ENABLE_DBG 1 #include "../log.h" #include "../config.h" +#include "../config-verify.h" #include "../particle.h" struct private { diff --git a/particles/map.c b/particles/map.c index 405060e..99625d0 100644 --- a/particles/map.c +++ b/particles/map.c @@ -5,6 +5,7 @@ #define LOG_MODULE "map" #include "../log.h" #include "../config.h" +#include "../config-verify.h" #include "../particle.h" struct particle_map { diff --git a/particles/progress-bar.c b/particles/progress-bar.c index ff71b98..130bc76 100644 --- a/particles/progress-bar.c +++ b/particles/progress-bar.c @@ -6,6 +6,7 @@ #define LOG_ENABLE_DBG 0 #include "../log.h" #include "../config.h" +#include "../config-verify.h" #include "../particle.h" struct private { diff --git a/particles/ramp.c b/particles/ramp.c index f8b4091..0ef91b8 100644 --- a/particles/ramp.c +++ b/particles/ramp.c @@ -5,6 +5,7 @@ #include #include "../config.h" +#include "../config-verify.h" #include "../particle.h" struct private { diff --git a/particles/string.c b/particles/string.c index 1ebe4e4..7b66c86 100644 --- a/particles/string.c +++ b/particles/string.c @@ -6,6 +6,7 @@ #define LOG_ENABLE_DBG 1 #include "../log.h" #include "../config.h" +#include "../config-verify.h" #include "../particle.h" struct private { diff --git a/plugin.c b/plugin.c index 0786a56..b43a12f 100644 --- a/plugin.c +++ b/plugin.c @@ -15,8 +15,9 @@ static const char * type2str(enum plugin_type type) { switch (type) { - case PLUGIN_MODULE: return "module"; - case PLUGIN_PARTICLE: return "particle"; + case PLUGIN_MODULE: return "module"; + case PLUGIN_PARTICLE: return "particle"; + case PLUGIN_DECORATION: return "decoration"; } return NULL; @@ -53,10 +54,9 @@ plugin_load(const char *name, enum plugin_type type) } } + char path[128]; - snprintf( - path, sizeof(path), "%s_%s.so", - type == PLUGIN_MODULE ? "module" : "particle", name); + snprintf(path, sizeof(path), "%s_%s.so", type2str(type), name); /* Not loaded - do it now */ void *lib = dlopen(path, RTLD_LOCAL | RTLD_NOW); @@ -102,3 +102,10 @@ plugin_load_particle(const char *name) const struct plugin *plug = plugin_load(name, PLUGIN_PARTICLE); return plug != NULL ? &plug->particle : NULL; } + +const struct deco_iface * +plugin_load_deco(const char *name) +{ + const struct plugin *plug = plugin_load(name, PLUGIN_DECORATION); + return plug != NULL ? &plug->decoration : NULL; +} diff --git a/plugin.h b/plugin.h index aa910c7..2e923c9 100644 --- a/plugin.h +++ b/plugin.h @@ -4,22 +4,30 @@ #include "module.h" #include "particle.h" +typedef bool (*verify_func_t)(keychain_t *chain, const struct yml_node *node); + struct module_iface { - bool (*verify_conf)(keychain_t *chain, const struct yml_node *node); + verify_func_t verify_conf; struct module *(*from_conf)( const struct yml_node *node, struct conf_inherit inherited); }; struct particle_iface { - bool (*verify_conf)(keychain_t *chain, const struct yml_node *node); + verify_func_t verify_conf; struct particle *(*from_conf)( const struct yml_node *node, struct particle *common); }; +struct deco_iface { + verify_func_t verify_conf; + struct deco *(*from_conf)(const struct yml_node *node); +}; + const struct module_iface *plugin_load_module(const char *name); const struct particle_iface *plugin_load_particle(const char *name); +const struct deco_iface *plugin_load_deco(const char *name); -enum plugin_type { PLUGIN_MODULE, PLUGIN_PARTICLE }; +enum plugin_type { PLUGIN_MODULE, PLUGIN_PARTICLE, PLUGIN_DECORATION }; struct plugin { char *name; @@ -34,6 +42,7 @@ struct plugin { struct module_iface module; struct particle_iface particle; + struct deco_iface decoration; }; };