aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/action.c8
-rw-r--r--src/action.h4
-rw-r--r--src/block.c22
-rw-r--r--src/block.h8
-rw-r--r--src/blocks/group.c57
-rw-r--r--src/blocks/slider.c64
-rw-r--r--src/comet.c2
-rw-r--r--src/config.c133
-rw-r--r--src/config.h4
-rw-r--r--src/util.c2
-rw-r--r--src/util.h4
11 files changed, 186 insertions, 122 deletions
diff --git a/src/action.c b/src/action.c
index 1ea7d7f..3a358c3 100644
--- a/src/action.c
+++ b/src/action.c
@@ -124,10 +124,16 @@ error:
int action_validate(action_t *action, config_t *config)
{
- // TODO
+ action->validated = true;
return 0;
}
+bool action_resolve(action_t *action, config_t *config)
+{
+ action->resolved = true;
+ return true;
+}
+
void action_free(action_t *action)
{
for (size_t i = 0; i < action->length; i++) {
diff --git a/src/action.h b/src/action.h
index 712bf81..795a79c 100644
--- a/src/action.h
+++ b/src/action.h
@@ -22,6 +22,8 @@ struct action {
char *label;
action_part_t *parts;
size_t length;
+ bool validated;
+ bool resolved;
};
typedef struct action action_t;
@@ -30,6 +32,8 @@ bool action_perform(action_t *action, block_t *block, config_t *config);
int action_validate(action_t *action, config_t *config);
+bool action_resolve(action_t *action, config_t *config);
+
void action_free(action_t *action);
#endif
diff --git a/src/block.c b/src/block.c
index 1786502..04ad902 100644
--- a/src/block.c
+++ b/src/block.c
@@ -3,6 +3,7 @@
#include "block.h"
#include "util.h"
+#include "action.h"
#include "any_log.h"
extern const block_scheme_t block_text_scheme;
@@ -50,6 +51,27 @@ void block_update(block_t *block)
}
}
+bool block_resolve(block_t *block, config_t *config)
+{
+ if (block->resolved)
+ return true;
+
+ block->resolved = true;
+
+ for (size_t i = 0; i < EVENT_MAX; i++) {
+ char *action = (char *)block->actions[i];
+ if (action == NULL) continue;
+
+ if (!config_resolve_action(config, action, &block->actions[i]))
+ return false;
+
+ free(action);
+ }
+
+ return block->scheme->resolve_fn == NULL
+ || block->scheme->resolve_fn(block, config);
+}
+
bool block_change(block_t *block, config_t *config, const char *key, const char *value)
{
extern const config_entry_t block_entries[];
diff --git a/src/block.h b/src/block.h
index be62d20..940231a 100644
--- a/src/block.h
+++ b/src/block.h
@@ -54,6 +54,7 @@ struct block {
const block_scheme_t *scheme;
bool validated;
bool resolved;
+ bool grouped;
bool hidden;
struct timespec update_interval;
struct timespec update_last;
@@ -104,6 +105,10 @@ typedef void (*block_clean_t)(block_t *block);
//
typedef int (*block_validate_t)(block_t *block, config_t *config);
+// Called to resolve references in the block
+//
+typedef bool (*block_resolve_t)(block_t *block, config_t *config);
+
// Called to validate changes to a block variable
//
typedef config_status_t (*block_change_t)(block_t *block, config_t *config, const char *key, const char *value);
@@ -116,6 +121,7 @@ struct block_scheme {
block_init_t init_fn;
block_clean_t clean_fn;
block_validate_t validate_fn;
+ block_resolve_t resolve_fn;
block_change_t change_fn;
};
@@ -123,6 +129,8 @@ extern const block_scheme_t *block_schemes[];
void block_update(block_t *block);
+bool block_resolve(block_t *block, config_t *config);
+
bool block_change(block_t *block, config_t *config, const char *key, const char *value);
void block_free(block_t *block);
diff --git a/src/blocks/group.c b/src/blocks/group.c
index eeac132..da9e6d6 100644
--- a/src/blocks/group.c
+++ b/src/blocks/group.c
@@ -1,3 +1,5 @@
+#include <assert.h>
+
#include "../block.h"
#include "../any_log.h"
@@ -12,6 +14,60 @@ static void block_group_clean(block_t *block)
free(group->children);
}
+static bool block_group_resolve(block_t *block, config_t *config)
+{
+ block_group_t *group = (block_group_t *)block;
+ assert(block->type == BLOCK_GROUP);
+
+ char **children = (char **)group->children;
+ group->children = NULL;
+ group->n_children = 0;
+
+ if (children == NULL)
+ return true;
+
+ while (children[group->n_children] != NULL)
+ group->n_children++;
+
+ group->children = malloc(group->n_children * sizeof(block_t *));
+ bool result = true;
+
+ for (size_t i = 0; i < group->n_children; i++) {
+ for (size_t j = 0; j < config->n_blocks; j++) {
+ if (config->blocks[j] == block)
+ continue;
+
+ if (!strcmp(children[i], config->blocks[j]->label)) {
+ if (config->blocks[j]->grouped) {
+ log_error("Block '%s' can only be in one group", children[i]);
+ result = false;
+ goto end;
+ }
+
+ log_debug("Block '%s' is parent of '%s'", block->label, children[i]);
+ group->children[i] = config->blocks[j];
+ group->children[i]->grouped = true;
+
+ if (!block_resolve(group->children[i], config)) {
+ result = false;
+ goto end;
+ }
+
+ goto next;
+ }
+ }
+
+ log_error("Block '%s' not found (referenced by '%s')", children[i], block->label);
+ result = false;
+ goto end;
+next:
+ }
+
+end:
+ strfreelist(children);
+ return result;
+}
+
static config_status_t block_group_change(block_t *block, config_t *config, const char *key, const char *value)
{
if (!strcmp(key, "blocks")) {
@@ -30,5 +86,6 @@ const block_scheme_t block_group_scheme = {
.init_fn = block_group_init,
.clean_fn = block_group_clean,
.validate_fn = NULL,
+ .resolve_fn = block_group_resolve,
.change_fn = block_group_change,
};
diff --git a/src/blocks/slider.c b/src/blocks/slider.c
index 34d6c35..1b5d4c3 100644
--- a/src/blocks/slider.c
+++ b/src/blocks/slider.c
@@ -34,6 +34,9 @@ typedef struct {
gradient_t knob_color;
gradient_t knob_line_color;
double knob_rotation;
+ action_t *left_click;
+ action_t *middle_click;
+ action_t *right_click;
} block_slider_t;
static void block_slider_layout(block_t *block, layout_t *layout, layout_info_t info)
@@ -242,6 +245,29 @@ static int block_slider_validate(block_t *block, config_t *config)
return errors;
}
+static bool block_slider_resolve(block_t *block, config_t *config)
+{
+ block_slider_t *slider = (block_slider_t *)block;
+
+ action_t **actions[] = {
+ &slider->left_click,
+ &slider->middle_click,
+ &slider->right_click,
+ };
+
+ for (size_t i = 0; i < 3; i++) {
+ char *label = (char *)*actions[i];
+ if (label == NULL) continue;
+
+ if (!config_resolve_action(config, label, actions[i]))
+ return false;
+
+ free(label);
+ }
+
+ return true;
+}
+
static config_enum_t knob_shape_enum[] = {
{ "none", KNOB_NONE },
{ "capsule", KNOB_CAPSULE },
@@ -252,23 +278,26 @@ static config_enum_t knob_shape_enum[] = {
static const config_entry_t block_slider_entries[] = {
// TODO: Ugly names
- { "bar-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, bar_color) },
- { "bar-line-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, line_color) },
- { "bar-bg-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, bg_color) },
- { "bar-height", CONFIG_UINT, NULL, offsetof(block_slider_t, height) },
- { "bar-width", CONFIG_UINT, NULL, offsetof(block_slider_t, width) },
- { "bar-line-width", CONFIG_UINT, NULL, offsetof(block_slider_t, line_width) },
- { "bar-value", CONFIG_INT, NULL, offsetof(block_slider_t, value) },
- { "seekable", CONFIG_BOOL, NULL, offsetof(block_slider_t, seekable) },
- { "knob", CONFIG_ENUM, knob_shape_enum, offsetof(block_slider_t, knob) },
- { "knob-height", CONFIG_UINT, NULL, offsetof(block_slider_t, knob_height) },
- { "knob-width", CONFIG_UINT, NULL, offsetof(block_slider_t, knob_width) },
- { "knob-line-width", CONFIG_UINT, NULL, offsetof(block_slider_t, knob_line_width) },
- { "knob-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, knob_color) },
- { "knob-line-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, knob_line_color) },
- { "knob-x-offset", CONFIG_INT, NULL, offsetof(block_slider_t, knob_x_offset) },
- { "knob-y-offset", CONFIG_INT, NULL, offsetof(block_slider_t, knob_y_offset) },
- { "knob-rotation", CONFIG_DOUBLE, NULL, offsetof(block_slider_t, knob_rotation) },
+ { "bar-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, bar_color) },
+ { "bar-line-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, line_color) },
+ { "bar-bg-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, bg_color) },
+ { "bar-height", CONFIG_UINT, NULL, offsetof(block_slider_t, height) },
+ { "bar-width", CONFIG_UINT, NULL, offsetof(block_slider_t, width) },
+ { "bar-line-width", CONFIG_UINT, NULL, offsetof(block_slider_t, line_width) },
+ { "bar-value", CONFIG_INT, NULL, offsetof(block_slider_t, value) },
+ { "seekable", CONFIG_BOOL, NULL, offsetof(block_slider_t, seekable) },
+ { "knob", CONFIG_ENUM, knob_shape_enum, offsetof(block_slider_t, knob) },
+ { "knob-height", CONFIG_UINT, NULL, offsetof(block_slider_t, knob_height) },
+ { "knob-width", CONFIG_UINT, NULL, offsetof(block_slider_t, knob_width) },
+ { "knob-line-width", CONFIG_UINT, NULL, offsetof(block_slider_t, knob_line_width) },
+ { "knob-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, knob_color) },
+ { "knob-line-color", CONFIG_GRADIENT, NULL, offsetof(block_slider_t, knob_line_color) },
+ { "knob-x-offset", CONFIG_INT, NULL, offsetof(block_slider_t, knob_x_offset) },
+ { "knob-y-offset", CONFIG_INT, NULL, offsetof(block_slider_t, knob_y_offset) },
+ { "knob-rotation", CONFIG_DOUBLE, NULL, offsetof(block_slider_t, knob_rotation) },
+ { "left-click-bar", CONFIG_STRING, NULL, offsetof(block_slider_t, left_click) },
+ { "middle-click-bar", CONFIG_STRING, NULL, offsetof(block_slider_t, middle_click) },
+ { "right-click-bar", CONFIG_STRING, NULL, offsetof(block_slider_t, right_click) },
{ 0 },
};
@@ -285,5 +314,6 @@ const block_scheme_t block_slider_scheme = {
.init_fn = block_slider_init,
.clean_fn = block_slider_clean,
.validate_fn = block_slider_validate,
+ .resolve_fn = block_slider_resolve,
.change_fn = block_slider_change,
};
diff --git a/src/comet.c b/src/comet.c
index 9ff848c..8cd9f24 100644
--- a/src/comet.c
+++ b/src/comet.c
@@ -112,7 +112,7 @@ int main(int argc, char **argv)
};
block_t *block = NULL;
- if (config_resolve(&config, &block) > 0) {
+ if (!config_resolve(&config, &block)) {
log_error("Config could not be resolved");
return EXIT_FAILURE;
}
diff --git a/src/config.c b/src/config.c
index c8b63b4..e7c47d7 100644
--- a/src/config.c
+++ b/src/config.c
@@ -205,8 +205,8 @@ static bool config_read_color(const char *value, color_t *result)
static bool config_read_gradient(const char *value, gradient_t *result)
{
- // TODO: Ensure that this is correct
gradient_free(result);
+ memset(result, 0, sizeof(gradient_t));
size_t count = 0;
for (size_t i = 0; value[i] != '\0'; ++i)
@@ -235,15 +235,15 @@ static bool config_read_gradient(const char *value, gradient_t *result)
}
free(copy);
- result->colors = colors;
- result->length = n;
-
if (n == 0) {
free(colors);
log_debug("Expected at least one color");
return false;
}
+ result->colors = colors;
+ result->length = n;
+
if (n == 1) {
result->pattern = cairo_pattern_create_rgba(colors->r, colors->g, colors->b, colors->a);
return true;
@@ -289,8 +289,8 @@ static bool config_read_time(const char *value, struct timespec *result)
// TODO: Handle quotation marks
static bool config_read_list(const char *value, char ***result)
{
- // TODO: Ensure that this is correct
- strfree(*result);
+ strfreelist(*result);
+ *result = NULL;
size_t count = 0;
for (size_t i = 0; value[i] != '\0'; ++i)
@@ -312,9 +312,9 @@ static bool config_read_list(const char *value, char ***result)
*end = '\0';
if (!config_read_string(token, &list[n++])) {
- free(copy);
list[n] = NULL;
- strfree(list);
+ strfreelist(list);
+ free(copy);
return false;
}
}
@@ -716,6 +716,12 @@ skip_pair:
int config_validate(config_t *config)
{
int errors = 0;
+ block_group_t *bar = (block_group_t *)config->blocks[0];
+
+ if (bar->children == NULL) {
+ log_error("Section '%s' requires at least one child", "bar");
+ errors++;
+ }
// Validate the config itself
if (config->scale < 1 && config->scale != 0) {
@@ -737,7 +743,6 @@ int config_validate(config_t *config)
}
// Validate actions
- // NOTE: Maybe move this after the config is resolved?
//
for (size_t i = 0; i < config->n_actions; i++) {
action_t *action = &config->actions[i];
@@ -748,109 +753,41 @@ int config_validate(config_t *config)
return errors;
}
-bool config_resolve_action(config_t *config, block_t *block)
+bool config_resolve_action(config_t *config, const char *label, action_t **action)
{
- action_t *actions[EVENT_MAX] = { 0 };
-
- for (size_t i = 0; i < EVENT_MAX; i++) {
- char *label = (char *)block->actions[i];
-
- if (label == NULL)
- continue;
-
- for (size_t j = 0; j < config->n_actions; j++) {
- if (!strcmp(label, config->actions[j].label)) {
- log_debug("Block '%s' uses action '%s' for %s", block->label, label, event_type_to_string(i));
-
- actions[i] = &config->actions[j];
- free(label);
- goto next;
- }
+ for (size_t j = 0; j < config->n_actions; j++) {
+ if (!strcmp(label, config->actions[j].label)) {
+ *action = &config->actions[j];
+ return true;
}
-
- log_error("Action '%s' not found (referenced by '%s')", label, block->label);
- return false;
-next:
}
- memcpy(block->actions, actions, sizeof(actions));
- return true;
+ log_error("Action '%s' not found", label);
+ return false;
}
-bool config_resolve_children(config_t *config, block_t *block)
+bool config_resolve(config_t *config, block_t **block)
{
- block->resolved = true;
-
- if (!config_resolve_action(config, block))
- return false;
-
- if (block->type != BLOCK_GROUP)
- return true;
-
- assert(block->type == BLOCK_GROUP);
- block_group_t *group = (block_group_t *)block;
-
- char **children = (char **)group->children;
- group->children = NULL;
- group->n_children = 0;
-
- if (children == NULL)
- return true;
-
- while (children[group->n_children] != NULL)
- group->n_children++;
-
- group->children = malloc(group->n_children * sizeof(block_t *));
-
- for (size_t i = 0; i < group->n_children; i++) {
- for (size_t j = 0; j < config->n_blocks; j++) {
- if (config->blocks[j] == block)
- continue;
-
- if (!strcmp(children[i], config->blocks[j]->label)) {
- if (config->blocks[j]->resolved) {
- log_error("Block '%s' can only be referenced by one block", children[i]);
- goto error;
- }
-
- log_debug("Block '%s' is parent of '%s'", block->label, children[i]);
- group->children[i] = config->blocks[j];
-
- if (!config_resolve_children(config, config->blocks[j]))
- goto error;
- goto next;
- }
- }
+ block_group_t *bar = (block_group_t *)config->blocks[0];
+ assert(bar->children != NULL);
- log_error("Block '%s' not found (referenced by '%s')", children[i], block->label);
- goto error;
-next:
+ for (size_t i = 0; i < config->n_actions; i++) {
+ if (!action_resolve(&config->actions[i], config))
+ return false;
}
- strfree(children);
- return true;
-
-error:
- strfree(children);
- return false;
-}
-
-int config_resolve(config_t *config, block_t **block)
-{
- int errors = 0;
- block_group_t *bar = (block_group_t *)config->blocks[0];
+ log_debug("Resolved %zu actions", config->n_actions);
- if (bar->children == NULL) {
- errors++;
- log_error("Section '%s' requires at least one child", "bar");
- } else {
- // NOTE: The first item is the main block
- bar->block.min_width = bar->block.max_width = config->width;
- errors += !config_resolve_children(config, config->blocks[0]);
+ for (size_t i = 0; i < config->n_blocks; i++) {
+ if (!block_resolve(config->blocks[i], config))
+ return false;
}
+ log_debug("Resolved %zu blocks", config->n_blocks);
+
*block = config->blocks[0];
- return errors;
+ bar->block.min_width = bar->block.max_width = config->width;
+ return true;
}
void config_free(config_t *config)
diff --git a/src/config.h b/src/config.h
index 9a26615..6a13ab3 100644
--- a/src/config.h
+++ b/src/config.h
@@ -73,9 +73,9 @@ int config_read(config_t *config, FILE *file);
int config_validate(config_t *config);
-bool config_resolve_children(config_t *config, block_t *block);
+bool config_resolve_action(config_t *config, const char *label, action_t **action);
-int config_resolve(config_t *config, block_t **block);
+bool config_resolve(config_t *config, block_t **block);
void config_free(config_t *config);
diff --git a/src/util.c b/src/util.c
index 6001a31..0c58808 100644
--- a/src/util.c
+++ b/src/util.c
@@ -194,7 +194,7 @@ size_t strprefix(const char *string, const char *prefix)
return i;
}
-void strfree(char **list)
+void strfreelist(char **list)
{
if (list == NULL)
return;
diff --git a/src/util.h b/src/util.h
index 2326c8d..390bc88 100644
--- a/src/util.h
+++ b/src/util.h
@@ -81,10 +81,10 @@ bool strfind(const char *string, const char *cases[]);
size_t strprefix(const char *string, const char *prefix);
-void strfree(char **list);
-
bool iszero(const void *ptr, size_t size);
+void strfreelist(char **list);
+
double steps(double value, int n);
void render_triangle(cairo_t *cr, int x, int y, int w, int h);