diff --git a/data/themerc b/data/themerc new file mode 100644 index 00000000..a413a14a --- /dev/null +++ b/data/themerc @@ -0,0 +1 @@ +window.active.title.bg.color: #589bda diff --git a/include/theme.h b/include/theme.h new file mode 100644 index 00000000..a6b5d125 --- /dev/null +++ b/include/theme.h @@ -0,0 +1,14 @@ +#ifndef THEME_H +#define THEME_H + +#include + +struct theme { + float window_active_title_bg_color[4]; +}; + +extern struct theme theme; + +void theme_read(const char *filename); + +#endif /* THEME_H */ diff --git a/src/main.c b/src/main.c index c2591bd8..23547c09 100644 --- a/src/main.c +++ b/src/main.c @@ -1,8 +1,10 @@ #include "labwc.h" #include "rcxml.h" +#include "theme.h" struct server server = { 0 }; struct rcxml rc = { 0 }; +struct theme theme = { 0 }; int main(int argc, char *argv[]) { @@ -27,6 +29,7 @@ int main(int argc, char *argv[]) rcxml_init(&rc); rcxml_read("data/rc.xml"); + theme_read("data/themerc"); /* Wayland requires XDG_RUNTIME_DIR to be set */ if (!getenv("XDG_RUNTIME_DIR")) { diff --git a/src/meson.build b/src/meson.build index e76b4fb4..5895d465 100644 --- a/src/meson.build +++ b/src/meson.build @@ -13,4 +13,5 @@ labwc_sources = files( subdir('common') subdir('config') +subdir('theme') subdir('debug') diff --git a/src/output.c b/src/output.c index e5a23bcf..eec3ce08 100644 --- a/src/output.c +++ b/src/output.c @@ -1,7 +1,7 @@ #include "labwc.h" #include "rcxml.h" +#include "theme.h" -static float window_active_title_bg[] = { 0.29, 0.55, 0.78, 1.0 }; static float window_active_handle_bg[] = { 0.21, 0.49, 0.71, 1.0 }; struct draw_data { @@ -54,7 +54,7 @@ static void render_decorations(struct wlr_output *output, struct view *view) draw_rect(&ddata, deco_box(view, LAB_DECO_PART_BOTTOM)); draw_rect(&ddata, deco_box(view, LAB_DECO_PART_LEFT)); - ddata.rgba = window_active_title_bg; + ddata.rgba = theme.window_active_title_bg_color; draw_rect(&ddata, deco_box(view, LAB_DECO_PART_TITLE)); } diff --git a/src/theme/meson.build b/src/theme/meson.build new file mode 100644 index 00000000..3b9ec5dc --- /dev/null +++ b/src/theme/meson.build @@ -0,0 +1,3 @@ +labwc_sources += files( + 'theme.c', +) diff --git a/src/theme/theme.c b/src/theme/theme.c new file mode 100644 index 00000000..868450e3 --- /dev/null +++ b/src/theme/theme.c @@ -0,0 +1,99 @@ +#define _POSIX_C_SOURCE 200809L +#include +#include +#include +#include + +#include "theme.h" + +static int hex_to_dec(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return 0; +} + +static void parse_hexstr(const char *hex, float *rgba) +{ + if (!hex || hex[0] != '#' || strlen(hex) < 7) + return; + rgba[0] = (hex_to_dec(hex[1]) * 16 + hex_to_dec(hex[2])) / 255.0; + rgba[1] = (hex_to_dec(hex[3]) * 16 + hex_to_dec(hex[4])) / 255.0; + rgba[2] = (hex_to_dec(hex[5]) * 16 + hex_to_dec(hex[6])) / 255.0; + if (strlen(hex) > 7) + rgba[3] = atoi(hex + 7) / 100.0; + else + rgba[3] = 1.0; +} + +static void entry(const char *key, const char *value) +{ + if (!key || !value) + return; + if (!strcmp(key, "window.active.title.bg.color")) + parse_hexstr(value, theme.window_active_title_bg_color); +} + +static void rtrim(char **s) +{ + size_t len = strlen(*s); + if (!len) + return; + char *end = *s + len - 1; + while (end >= *s && isspace(*end)) + end--; + *(end + 1) = '\0'; +} + +static char *strstrip(char *s) +{ + rtrim(&s); + while (isspace(*s)) + s++; + return s; +} + +static void parse_config_line(char *line, char **key, char **value) +{ + char *p = strchr(line, ':'); + if (!p) + return; + *p = '\0'; + *key = strstrip(line); + *value = strstrip(++p); +} + +static void process_line(char *line) +{ + if (line[0] == '\0' || line[0] == '#') + return; + char *key = NULL, *value = NULL; + parse_config_line(line, &key, &value); + entry(key, value); +} + +void theme_read(const char *filename) +{ + FILE *stream; + char *line = NULL; + size_t len = 0; + ssize_t n_read; + + stream = fopen(filename, "r"); + if (!stream) { + fprintf(stderr, "warn: cannot read '%s'\n", filename); + return; + } + while ((n_read = getline(&line, &len, stream) != -1)) { + char *p = strrchr(line, '\n'); + if (p) + *p = '\0'; + process_line(line); + } + free(line); + fclose(stream); +} diff --git a/tools/theme/.gitignore b/tools/theme/.gitignore new file mode 100644 index 00000000..c4938022 --- /dev/null +++ b/tools/theme/.gitignore @@ -0,0 +1 @@ +theme-helper diff --git a/tools/theme/Makefile b/tools/theme/Makefile new file mode 100644 index 00000000..4e83d616 --- /dev/null +++ b/tools/theme/Makefile @@ -0,0 +1,8 @@ +CFLAGS = -g -Wall -Wextra -pedantic -std=c11 +CFLAGS += -I../../include/ +ASAN_FLAGS = -O0 -fsanitize=address -fno-common -fno-omit-frame-pointer -rdynamic +CFLAGS += $(ASAN_FLAGS) +LDFLAGS += $(ASAN_FLAGS) -fuse-ld=gold + +all: + gcc $(CFLAGS) -o theme-helper theme-helper.c ../../src/theme/theme.c $(LDFLAGS) diff --git a/tools/theme/theme-helper.c b/tools/theme/theme-helper.c new file mode 100644 index 00000000..3c917d73 --- /dev/null +++ b/tools/theme/theme-helper.c @@ -0,0 +1,14 @@ +#include +#include + +#include "../../include/theme.h" + +struct theme theme = { 0 }; + +int main() +{ + theme_read("../../data/themerc"); + for (int i=0; i < 4; i++) + printf("%.2f; ", theme.window_active_title_bg_color[i]); + printf("\n"); +}