aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorFederico Angelilli <code@fedang.net>2024-11-12 00:36:47 +0100
committerFederico Angelilli <code@fedang.net>2024-11-12 00:36:47 +0100
commit686802c2a472746a1b40fab30cbb0351e536c9ba (patch)
tree9a4fe3fa654fbe7b9bb35893a2da71c9754745b4 /src
parent3f2af32442b9384d316651d42ad35945533dc39e (diff)
Modify block struct
Diffstat (limited to 'src')
-rw-r--r--src/block.c60
-rw-r--r--src/block.h71
-rw-r--r--src/blocks/scheme.h2
-rw-r--r--src/config.c94
-rw-r--r--src/config.h11
-rw-r--r--src/event.c11
-rw-r--r--src/layout.c138
-rw-r--r--src/layout.h4
8 files changed, 238 insertions, 153 deletions
diff --git a/src/block.c b/src/block.c
index 29a8394..f735174 100644
--- a/src/block.c
+++ b/src/block.c
@@ -1,4 +1,5 @@
#include <string.h>
+#include <assert.h>
#include "block.h"
#include "util.h"
@@ -6,7 +7,7 @@
void block_update(block_t *block)
{
- if (block->update_cb != NULL) {
+ if (block->update_fn != NULL) {
struct timespec now, diff;
timespec_get(&now, TIME_UTC);
diff = timespec_diff(now, block->update_last);
@@ -16,47 +17,50 @@ void block_update(block_t *block)
"s:label", block->label,
"g:ts", ANY_LOG_FORMATTER(timespec_print), &now);
- block->update_cb(block);
+ block->update_fn(block);
block->update_last = now;
}
}
+ // NOTE: Block spec should handle its children by itself...
+ //
if (block->type == BLOCK_GROUP) {
- for (int i = 0; i < block->group.n_children; i++)
- block_update(block->group.children[i]);
+ block_group_t *group = (block_group_t *)block;
+ for (size_t i = 0; i < group->n_children; i++)
+ block_update(group->children[i]);
}
}
void block_copy(block_t *copy, const block_t *block)
{
- memcpy(copy, block, sizeof(block_t));
-
- // NOTE: Strings must be copied
- copy->label = strcopy(block->label);
-
- if (block->type == BLOCK_TEXT) {
- copy->text.text = strcopy(block->text.text);
- } else if (block->type == BLOCK_GROUP) {
- copy->group.children = calloc(block->group.n_children, sizeof(block_t *));
-
- for (int i = 0; i < block->group.n_children; i++) {
- block->group.children[i] = malloc(sizeof(block_t));
- block_copy(block->group.children[i], copy->group.children[i]);
- }
- }
+// memcpy(copy, block, sizeof(block_t));
+//
+// // NOTE: Strings must be copied
+// copy->label = strcopy(block->label);
+//
+// if (block->type == BLOCK_TEXT) {
+// copy->text.text = strcopy(block->text.text);
+// } else if (block->type == BLOCK_GROUP) {
+// copy->group.children = calloc(block->group.n_children, sizeof(block_t *));
+//
+// for (int i = 0; i < block->group.n_children; i++) {
+// block->group.children[i] = malloc(sizeof(block_t));
+// block_copy(block->group.children[i], copy->group.children[i]);
+// }
+// }
}
// NOTE: This does not recursively free groups!
void block_free(block_t *block)
{
free(block->label);
-
- if (block->type == BLOCK_TEXT) {
- free(block->text.text);
- } else if (block->type == BLOCK_GROUP) {
- free(block->group.children);
- }
-
- if (block->finalize_cb != NULL)
- block->finalize_cb(block);
+//
+// if (block->type == BLOCK_TEXT) {
+// free(block->text.text);
+// } else if (block->type == BLOCK_GROUP) {
+// free(block->group.children);
+// }
+//
+ assert(block->clean_fn != NULL);
+ block->clean_fn(block);
}
diff --git a/src/block.h b/src/block.h
index 4254355..d9800ee 100644
--- a/src/block.h
+++ b/src/block.h
@@ -7,7 +7,7 @@
#include "event.h"
#include "util.h"
-#include "config.h"
+#include "layout.h"
// Element or text alignment
//
@@ -22,6 +22,7 @@ typedef enum {
typedef enum {
BLOCK_TEXT,
BLOCK_GROUP,
+ BLOCK_SPEC,
} block_type_t;
typedef struct block block_t;
@@ -34,45 +35,69 @@ typedef void (*block_event_t)(block_t *block, event_t event);
//
typedef void (*block_update_t)(block_t *block);
-// Block finalization routine
-// NOTE: The block state must be freed by this function
+// Called to cleanup a block and free its memory
//
-typedef void (*block_finalize_t)(block_t *block);
+typedef void (*block_clean_t)(block_t *block);
-// Block struct
+// Called in layout_init
+//
+typedef void (*block_layout_t)(block_t *block, layout_t *layout, layout_info_t info);
+
+// Called in layout_render
+//
+typedef void (*block_render_t)(layout_t *layout, cairo_t *cr);
+
+// Called in config_resolve_children
+//
+typedef struct config config_t;
+
+typedef bool (*block_resolve_t)(block_t *block, config_t *config);
+
+// The block struct
//
struct block {
block_type_t type;
char *label;
bool resolved;
bool hidden;
- void *state;
struct timespec update_interval;
struct timespec update_last;
- block_update_t update_cb;
- block_event_t event_cb;
- block_finalize_t finalize_cb;
+ block_update_t update_fn;
+ block_event_t event_fn;
+ block_clean_t clean_fn;
+ // TODO
+ //gradient_t bg_color;
+ //gradient_t line_color;
color_t color;
color_t line_color;
unsigned int line_width;
unsigned int x_padding, y_padding;
unsigned int min_width, max_width;
- union {
- struct {
- char *text;
- color_t text_color;
- align_t text_align;
- unsigned int text_size;
- } text;
- struct {
- unsigned int spacing;
- size_t n_children;
- struct block **children;
- bool collapse;
- } group;
- };
};
+typedef struct {
+ block_t block;
+ char *text;
+ color_t text_color;
+ align_t text_align;
+ unsigned int text_size;
+} block_text_t;
+
+typedef struct {
+ block_t block;
+ unsigned int spacing;
+ size_t n_children;
+ struct block **children;
+ bool collapse;
+} block_group_t;
+
+typedef struct {
+ block_t block;
+ block_layout_t layout_fn;
+ block_render_t render_fn;
+ block_resolve_t resolve_fn;
+} block_spec_t;
+
void block_update(block_t *block);
void block_copy(block_t *copy, const block_t *block);
diff --git a/src/blocks/scheme.h b/src/blocks/scheme.h
index 1795013..b726afe 100644
--- a/src/blocks/scheme.h
+++ b/src/blocks/scheme.h
@@ -1,7 +1,7 @@
#ifndef COMET_SCHEME_H
#define COMET_SCHEME_H
-#include "../block.h"
+#include "../config.h"
typedef struct block_scheme block_scheme_t;
diff --git a/src/config.c b/src/config.c
index 84804bc..0d48ef6 100644
--- a/src/config.c
+++ b/src/config.c
@@ -44,9 +44,9 @@ static const config_entry_t block_entries[] = {
};
static const config_entry_t block_group_entries[] = {
- { "spacing", CONFIG_UINT, NULL, offsetof(block_t, group.spacing) },
- { "blocks", CONFIG_LIST, NULL, offsetof(block_t, group.children) },
- { "collapse", CONFIG_BOOL, NULL, offsetof(block_t, group.collapse) },
+ { "spacing", CONFIG_UINT, NULL, offsetof(block_group_t, spacing) },
+ { "blocks", CONFIG_LIST, NULL, offsetof(block_group_t, children) },
+ { "collapse", CONFIG_BOOL, NULL, offsetof(block_group_t, collapse) },
{ 0 },
};
@@ -58,10 +58,10 @@ static config_enum_t text_align_enum[] = {
};
static const config_entry_t block_text_entries[] = {
- { "text", CONFIG_STRING, NULL, offsetof(block_t, text.text) },
- { "text-color", CONFIG_COLOR, NULL, offsetof(block_t, text.text_color) },
- { "text-size", CONFIG_UINT, NULL, offsetof(block_t, text.text_size) },
- { "text-align", CONFIG_ENUM, text_align_enum, offsetof(block_t, text.text_size) },
+ { "text", CONFIG_STRING, NULL, offsetof(block_text_t, text) },
+ { "text-color", CONFIG_COLOR, NULL, offsetof(block_text_t, text_color) },
+ { "text-size", CONFIG_UINT, NULL, offsetof(block_text_t, text_size) },
+ { "text-align", CONFIG_ENUM, text_align_enum, offsetof(block_text_t, text_size) },
{ 0 },
};
@@ -347,7 +347,7 @@ static config_status_t config_read_block(const block_scheme_t *scheme, block_t *
return status != CONFIG_UNKNOWN || scheme == NULL || scheme->entries == NULL
? status
- : config_read_entry(scheme->entries, block->state, type, section, key, value);
+ : config_read_entry(scheme->entries, block, type, section, key, value);
}
void config_init(config_t *config)
@@ -364,10 +364,10 @@ void config_init(config_t *config)
config->font = strcopy(config_default.font);
config->n_blocks = 1;
- config->blocks = calloc(1, sizeof(block_t));
- config->blocks->label = strcopy("bar");
- config->blocks->type = BLOCK_GROUP;
- config->blocks->group.spacing = 10;
+ config->blocks = calloc(1, sizeof(block_t *));
+ config->blocks[0]->label = strcopy("bar");
+ config->blocks[0]->type = BLOCK_GROUP;
+ //config->blocks->group.spacing = 10;
}
void config_read(config_t *config, FILE *file)
@@ -388,9 +388,9 @@ void config_read(config_t *config, FILE *file)
if (section != NULL) {
if (!strncmp(section, "block.", 6)) {
- config->blocks = realloc(config->blocks, ++config->n_blocks * sizeof(block_t));
+ config->blocks = realloc(config->blocks, ++config->n_blocks * sizeof(block_t *));
assert(config->blocks != NULL);
- block = &config->blocks[config->n_blocks - 1];
+ block = config->blocks[config->n_blocks - 1];
char *label = strcopy(section + 6);
if (label == NULL || *label == '\0' || !strcmp(label, "bar")) {
@@ -400,7 +400,7 @@ void config_read(config_t *config, FILE *file)
"i:line", ini.line);
} else {
for (size_t i = 0; i < config->n_blocks - 1; i++) {
- if (!strcmp(label, config->blocks[i].label)) {
+ if (!strcmp(label, config->blocks[i]->label)) {
++errors;
log_value_error("Block section must have a unique label",
"s:section", section,
@@ -436,10 +436,10 @@ void config_read(config_t *config, FILE *file)
free(block->label);
block->label = label;
- if (scheme->size != 0) {
- block->state = malloc(scheme->size);
- memset(block->state, 0, scheme->size);
- }
+ //if (scheme->size != 0) {
+ // block->state = malloc(scheme->size);
+ // memset(block->state, 0, scheme->size);
+ //}
goto skip_pair;
}
@@ -477,11 +477,11 @@ void config_read(config_t *config, FILE *file)
// Try the block entries
if (status == CONFIG_UNKNOWN)
- block = config->blocks;
+ block = config->blocks[0];
}
if (block != NULL) {
- status = config_read_block(scheme, &config->blocks[config->n_blocks - 1],
+ status = config_read_block(scheme, config->blocks[config->n_blocks - 1],
&type, section, key, value);
}
@@ -531,40 +531,48 @@ skip_pair:
log_panic("Config file contained %d errors", n_errors);
}
-static bool config_resolve_children(config_t *config, block_t *block)
+bool config_resolve_children(config_t *config, block_t *block)
{
block->resolved = true;
+
if (block->type == BLOCK_TEXT)
return true;
- char **children = (char **)block->group.children;
- block->group.children = NULL;
- block->group.n_children = 0;
+ if (block->type == BLOCK_SPEC) {
+ block_spec_t *spec = (block_spec_t *)block;
+ return spec->resolve_fn == NULL || spec->resolve_fn(block, config);
+ }
+
+ 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;
- size_t n = 0;
- for ( ; children[n] != NULL; n++);
+ while (children[group->n_children] != NULL)
+ group->n_children++;
- block->group.n_children = n;
- block->group.children = malloc(n * sizeof(block_t *));
+ group->children = malloc(group->n_children * sizeof(block_t *));
- for (size_t i = 0; i < n; i++) {
+ 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)
+ 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", config->blocks[j].label);
+ if (!strcmp(children[i], config->blocks[j]->label)) {
+ if (config->blocks[j]->resolved) {
+ log_error("Block '%s' can only be referenced by one block", config->blocks[j]->label);
return false;
}
- log_debug("Block '%s' is parent of '%s'", block->label, config->blocks[j].label);
- block->group.children[i] = &config->blocks[j];
+ log_debug("Block '%s' is parent of '%s'", block->label, config->blocks[j]->label);
+ group->children[i] = config->blocks[j];
- if (!config_resolve_children(config, &config->blocks[j]))
+ if (!config_resolve_children(config, config->blocks[j]))
return false;
goto next;
}
@@ -581,25 +589,27 @@ next:
block_t *config_resolve(config_t *config)
{
int errors = 0;
- if (config->blocks->group.children == NULL) {
+ block_group_t *bar = (block_group_t *)config->blocks[0];
+
+ if (bar->children == NULL) {
errors++;
log_error("Section '%s' requires at least one child", "bar");
} else {
// NOTE: The first item is the main block
- config->blocks->min_width = config->blocks->max_width = config->width;
- errors += !config_resolve_children(config, config->blocks);
+ bar->block.min_width = bar->block.max_width = config->width;
+ errors += !config_resolve_children(config, config->blocks[0]);
}
if (errors > 0)
log_panic("Config could not be resolved");
- return config->blocks;
+ return config->blocks[0];
}
void config_free(config_t *config)
{
for (int i = 0; i < config->n_blocks; i++)
- block_free(&config->blocks[i]);
+ block_free(config->blocks[i]);
free(config->blocks);
free(config->font);
diff --git a/src/config.h b/src/config.h
index a7d196f..48fd273 100644
--- a/src/config.h
+++ b/src/config.h
@@ -5,8 +5,9 @@
#include <stdint.h>
#include "util.h"
+#include "block.h"
-typedef struct block block_t;
+typedef struct config config_t;
typedef enum {
CONFIG_STRING,
@@ -27,16 +28,16 @@ typedef struct {
size_t offset;
} config_entry_t;
-typedef struct {
+struct config {
size_t n_blocks;
- block_t *blocks;
+ block_t **blocks;
char *font;
char *monitor;
bool override_redirect;
color_t background;
unsigned int width;
unsigned int height;
-} config_t;
+};
typedef struct {
const char *label;
@@ -47,6 +48,8 @@ void config_init(config_t *config);
void config_read(config_t *config, FILE *file);
+bool config_resolve_children(config_t *config, block_t *block);
+
block_t *config_resolve(config_t *config);
void config_free(config_t *config);
diff --git a/src/event.c b/src/event.c
index 0942fa1..39e408a 100644
--- a/src/event.c
+++ b/src/event.c
@@ -1,9 +1,10 @@
#include <assert.h>
+#include "any_log.h"
#include "util.h"
#include "layout.h"
#include "event.h"
-#include "any_log.h"
+#include "block.h"
const char *even_type_to_string(event_type_t type)
{
@@ -31,7 +32,7 @@ static bool event_click(layout_t *layout, event_t event)
return true;
}
- block_event_t event_cb = layout->block->event_cb;
+ block_event_t event_fn = layout->block->event_fn;
log_value_debug("Block was clicked",
"s:type", even_type_to_string(event.type),
"i:x", event.x,
@@ -41,10 +42,10 @@ static bool event_click(layout_t *layout, event_t event)
"i:block_y", layout->y,
"i:block_width", layout->width,
"i:block_height", layout->height,
- "b:callback", event_cb != NULL);
+ "b:callback", event_fn != NULL);
- if (event_cb != NULL) {
- event_cb(layout->block, event);
+ if (event_fn != NULL) {
+ event_fn(layout->block, event);
log_trace("Completed event callback");
}
diff --git a/src/layout.c b/src/layout.c
index 92e6469..db707c5 100644
--- a/src/layout.c
+++ b/src/layout.c
@@ -5,6 +5,7 @@
#include "any_log.h"
#include "layout.h"
+#include "block.h"
void layout_init(layout_t *layout, block_t *block, layout_info_t info)
{
@@ -19,49 +20,68 @@ void layout_init(layout_t *layout, block_t *block, layout_info_t info)
layout->y_padding = block->y_padding;
layout->height = info.height;
- if (block->type == BLOCK_GROUP) {
- int x_offset = info.x_offset;
- layout->children = calloc(block->group.n_children, sizeof(layout_t));
+ switch (block->type) {
+ case BLOCK_TEXT: {
+ block_text_t *text = (block_text_t *)block;
+ layout->pl = pango_layout_new(info.context);
- for (int i = 0; i < block->group.n_children; i++) {
- if (block->group.children[i]->hidden)
- continue;
+ pango_layout_set_font_description(layout->pl, info.fontdesc);
+ pango_layout_set_alignment(layout->pl, text->text_align);
+ pango_layout_set_height(layout->pl, 0);
+ pango_layout_set_text(layout->pl, text->text, -1);
+ pango_layout_get_pixel_size(layout->pl, &layout->text_width, &layout->text_height);
- layout_init(&layout->children[layout->n_children], block->group.children[i], info);
- info.x_offset += layout->children[layout->n_children].width + block->group.spacing;
- layout->n_children++;
+ size_t length = strlen(text->text);
+ layout->width = info.height + (length != 1) * layout->text_width;
+ break;
}
- if (block->group.collapse && layout->n_children == 1) {
- layout_t *children = layout->children;
- memcpy(layout, children, sizeof(layout_t));
- free(children);
+ case BLOCK_GROUP: {
+ block_group_t *group = (block_group_t *)block;
+ int x_offset = info.x_offset;
+ layout->children = calloc(group->n_children, sizeof(layout_t));
- } else if (layout->n_children > 0) {
- layout_t *last = &layout->children[layout->n_children - 1];
- layout->width = last->x + last->width - x_offset;
+ for (size_t i = 0; i < group->n_children; i++) {
+ if (group->children[i]->hidden)
+ continue;
- // NOTE: Temporary solution to make blocks not overlapping correctly
- // less noticeable
- if (layout->children[0].x_padding == 0) {
- layout->x += 1;
- layout->width -= 1;
+ layout_init(&layout->children[layout->n_children], group->children[i], info);
+ info.x_offset += layout->children[layout->n_children].width + group->spacing;
+ layout->n_children++;
}
- if (last->x_padding == 0)
- layout->width -= 1;
+ if (group->collapse && layout->n_children == 1) {
+ layout_t *children = layout->children;
+ memcpy(layout, children, sizeof(layout_t));
+ free(children);
+
+ } else if (layout->n_children > 0) {
+ layout_t *last = &layout->children[layout->n_children - 1];
+ layout->width = last->x + last->width - x_offset;
+
+ // NOTE: Temporary solution to make blocks not overlapping correctly
+ // less noticeable
+ if (layout->children[0].x_padding == 0) {
+ layout->x += 1;
+ layout->width -= 1;
+ }
+
+ if (last->x_padding == 0)
+ layout->width -= 1;
+ }
+ break;
}
- } else if (block->type == BLOCK_TEXT) {
- layout->pl = pango_layout_new(info.context);
- pango_layout_set_font_description(layout->pl, info.fontdesc);
- pango_layout_set_alignment(layout->pl, block->text.text_align);
- pango_layout_set_height(layout->pl, 0);
- pango_layout_set_text(layout->pl, block->text.text, -1);
- pango_layout_get_pixel_size(layout->pl, &layout->text_width, &layout->text_height);
+ case BLOCK_SPEC: {
+ block_spec_t *spec = (block_spec_t *)block;
+ // You are on your own
+ // TODO: Maybe check for layout correctness
+ spec->layout_fn(block, layout, info);
+ break;
+ }
- int length = strlen(block->text.text);
- layout->width = info.height + (length != 1) * layout->text_width;
+ default:
+ unreachable();
}
if (layout->block->max_width > 0 && layout->width > layout->block->max_width)
@@ -98,24 +118,46 @@ void layout_render(layout_t *layout, cairo_t *cr)
cairo_close_path(cr);
cairo_stroke(cr);
- if (layout->block->type == BLOCK_GROUP) {
- for (int i = 0; i < layout->n_children; i++) {
- cairo_push_group(cr);
- layout_render(&layout->children[i], cr);
- cairo_pop_group_to_source(cr);
- cairo_paint(cr);
+ switch (layout->block->type) {
+ case BLOCK_TEXT: {
+ block_text_t *text = (block_text_t *)layout->block;
+ assert(layout->n_children == 0);
+
+ int text_x = layout->x + (layout->width - layout->text_width) / 2;
+ int text_y = layout->y + (layout->height - layout->text_height) / 2;
+
+ color = text->text_color;
+ cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a);
+ cairo_move_to(cr, text_x, text_y);
+
+ pango_layout_set_text(layout->pl, text->text, -1);
+ pango_cairo_update_layout(cr, layout->pl);
+ pango_cairo_show_layout(cr, layout->pl);
+ break;
+ }
+
+ case BLOCK_GROUP: {
+ for (size_t i = 0; i < layout->n_children; i++) {
+ cairo_push_group(cr);
+ layout_render(&layout->children[i], cr);
+ cairo_pop_group_to_source(cr);
+ cairo_paint(cr);
+ }
+ break;
}
- } else if (layout->block->type == BLOCK_TEXT) {
- int text_x = layout->x + (layout->width - layout->text_width) / 2;
- int text_y = layout->y + (layout->height - layout->text_height) / 2;
- color = layout->block->text.text_color;
- cairo_set_source_rgba(cr, color.r, color.g, color.b, color.a);
- cairo_move_to(cr, text_x, text_y);
+ case BLOCK_SPEC: {
+ // NOTE: What if a special block adds children to the layout?
+ // For now do nothing and let them handle it, however
+ // this is a strange behavior in my opinion...
+ //
+ block_spec_t *spec = (block_spec_t *)layout->block;
+ spec->render_fn(layout, cr);
+ break;
+ }
- pango_layout_set_text(layout->pl, layout->block->text.text, -1);
- pango_cairo_update_layout(cr, layout->pl);
- pango_cairo_show_layout(cr, layout->pl);
+ default:
+ unreachable();
}
}
@@ -124,7 +166,7 @@ void layout_free(layout_t *layout)
if (layout->pl != NULL)
g_object_unref(layout->pl);
- for (int i = 0; i < layout->n_children; i++)
+ for (size_t i = 0; i < layout->n_children; i++)
layout_free(&layout->children[i]);
free(layout->children);
diff --git a/src/layout.h b/src/layout.h
index be63155..657ca41 100644
--- a/src/layout.h
+++ b/src/layout.h
@@ -5,7 +5,7 @@
#include <pango/pangocairo.h>
#include <pango/pango-types.h>
-#include "block.h"
+typedef struct block block_t;
typedef struct {
PangoFontDescription *fontdesc;
@@ -21,7 +21,7 @@ typedef struct layout {
int width, height;
int text_width, text_height;
PangoLayout *pl;
- int n_children;
+ size_t n_children;
struct layout *children;
} layout_t;