diff --git a/include/zdwm/config.h b/include/zdwm/config.h index 7bb8d50..bcbe600 100644 --- a/include/zdwm/config.h +++ b/include/zdwm/config.h @@ -140,6 +140,21 @@ typedef struct zdwm_api_t { zdwm_config_builder_t *builder, zdwm_binding_mode_id_t mode_id ); + + /** + * @brief 设置边框配置信息 + * + * @param builder 配置构建上下文 + * @param width 边框宽度 + * @param normal 普通窗口边框颜色 + * @param focused 焦点窗口边框颜色 + */ + void (*set_border_config)( + zdwm_config_builder_t *builder, + uint32_t width, + const char *normal, + const char *focused + ); } zdwm_api_t; /** diff --git a/src/base/color.c b/src/base/color.c new file mode 100644 index 0000000..05bc15c --- /dev/null +++ b/src/base/color.c @@ -0,0 +1,107 @@ +#include "color.h" + +#include +#include +#include +#include + +#include "base/log.h" + +/** + * @brief 将 16 进制的颜色配置转换成 uint32 格式的 rgba数据 + * + * @param hex 16 进制的颜色表示,支持的格式有 + * RGB/RGBA/RRGGBB/RRGGBBAA/#RGB/#RGBA/#RRGGBB/#RRGGBBAA + * @param rgba 返回数据的指针,解析结果会放到这个指针指向的内存中 + * @return 如果 hex 是一个能正常解析的颜色,返回 true ,否则返回 false + */ +static bool hex_color_to_rgba(const char *hex, uint32_t *rgba); +/** + * @brief 将 rgba 通道顺序的颜色转换成 argb 顺序 + * @description xcb 库用到的颜色需要是 argb 通道顺序 + */ +static uint32_t rgba_to_argb(uint32_t rgba); +/** + * @brief 提取颜色中的各个颜色通道数值 + * @param rgba uint32 表示的颜色 + * @param red red channel, range 0~1 + * @param green green channel, range 0~1 + * @param blue blue channel, range 0~1 + * @param alpha alpha channel, range 0~1 + */ +static void extract_color_channel( + const uint32_t rgba, + double *red, + double *green, + double *blue, + double *alpha +); + +void color_parse(const char *hex, color_t *const color) { + bool success = hex_color_to_rgba(hex, &color->rgba); + if (!success) fatal("invalid hex color: %s", hex); + + color->argb = rgba_to_argb(color->rgba); + extract_color_channel( + color->rgba, + &color->red, + &color->green, + &color->blue, + &color->alpha + ); +} + +bool hex_color_to_rgba(const char *hex, uint32_t *rgba) { + if (hex[0] == '#') hex++; + + size_t len = strlen(hex); + char extended[9] = {0}; + uint32_t color = 0x00000000; + + if (len == 3 || len == 4) { + extended[0] = extended[1] = hex[0]; + extended[2] = extended[3] = hex[1]; + extended[4] = extended[5] = hex[2]; + if (len == 3) { + extended[6] = extended[7] = 'F'; + } else { + extended[6] = extended[7] = hex[3]; + } + } else if (len == 6) { + strncpy(extended, hex, len); + extended[6] = extended[7] = 'F'; + } else if (len == 8) { + strncpy(extended, hex, len); + } else { + return false; + } + + color = strtoul(extended, nullptr, 16) & 0xffffffff; + *rgba = color; + return true; +} + +#define EXTRACE_COLOR_BIT(C, R) (((C) >> (R)) & 0xff) +uint32_t rgba_to_argb(uint32_t rgba) { + uint32_t r = EXTRACE_COLOR_BIT(rgba, 24); + uint32_t g = EXTRACE_COLOR_BIT(rgba, 16); + uint32_t b = EXTRACE_COLOR_BIT(rgba, 8); + uint32_t a = EXTRACE_COLOR_BIT(rgba, 0); + + uint32_t argb = (a << 24) | (r << 16) | (g << 8) | b; + return argb; +} + +#define COLOR_SPLIT(C, R) (EXTRACE_COLOR_BIT((C), (R)) / (double)0xff) +void extract_color_channel( + const uint32_t rgba, + double *red, + double *green, + double *blue, + double *alpha +) { + *red = COLOR_SPLIT(rgba, 24); + *green = COLOR_SPLIT(rgba, 16); + *blue = COLOR_SPLIT(rgba, 8); + *alpha = COLOR_SPLIT(rgba, 0); +} diff --git a/src/base/color.h b/src/base/color.h new file mode 100644 index 0000000..7f33ada --- /dev/null +++ b/src/base/color.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +typedef struct color_t { + uint32_t rgba; + uint32_t argb; + + /* RGBA color channels for Cairo, each channel in the range [0, 1] */ + double red, green, blue, alpha; +} color_t; + +/** + * @brief 解析 16 进制表示的颜色 + * + * @param hex 颜色的 16 进制表示,支持的格式有 + * RGB/RGBA/RRGGBB/RRGGBBAA/#RGB/#RGBA/#RRGGBB/#RRGGBBAA + * @param color 存储颜色值的结构体指针,不能为 nullptr + */ +void color_parse(const char *hex, color_t *const color); diff --git a/src/config/runtime_config.c b/src/config/runtime_config.c index 150cc1b..704d548 100644 --- a/src/config/runtime_config.c +++ b/src/config/runtime_config.c @@ -5,6 +5,7 @@ #include #include "base/array.h" +#include "base/color.h" #include "base/memory.h" #include "config/defaults.h" #include "config/loader.h" @@ -25,6 +26,7 @@ struct zdwm_config_builder_t { size_t workspace_count; size_t workspace_capacity; size_t output_count; + border_config_t border; binding_table_t *binding_table; }; @@ -183,6 +185,17 @@ static bool runtime_config_set_initial_mode( return binding_table_set_current_mode(builder->binding_table, mode_id); } +static void runtime_config_set_border_config( + zdwm_config_builder_t *builder, + uint32_t width, + const char *normal, + const char *focused +) { + builder->border.width = width; + color_parse(normal, &builder->border.normal_color); + color_parse(focused, &builder->border.focused_color); +} + static bool config_builder_finish( zdwm_config_builder_t *builder, runtime_init_desc_t *out @@ -193,6 +206,7 @@ static bool config_builder_finish( if (!layout_registry_move(&builder->layouts, &out->layouts)) return false; if (!rules_move(&builder->rules, &out->rules)) return false; + out->border = builder->border; out->binding_table = builder->binding_table; out->workspaces = builder->workspaces; out->workspace_count = builder->workspace_count; @@ -223,13 +237,14 @@ static bool runtime_config_build( .fullscreen = fullscreen, .maximize = maximize, }, - .register_layout = runtime_config_register_layout, - .define_workspace = runtime_config_define_workspace, - .add_rule = runtime_config_add_rule, - .add_mode = runtime_config_add_mode, - .bind = runtime_config_bind, - .set_default_mode = runtime_config_set_default_mode, - .set_initial_mode = runtime_config_set_initial_mode, + .register_layout = runtime_config_register_layout, + .define_workspace = runtime_config_define_workspace, + .add_rule = runtime_config_add_rule, + .add_mode = runtime_config_add_mode, + .bind = runtime_config_bind, + .set_default_mode = runtime_config_set_default_mode, + .set_initial_mode = runtime_config_set_initial_mode, + .set_border_config = runtime_config_set_border_config, }; bool ok = setup(&api, &builder, outputs, output_count) && config_builder_finish(&builder, out); diff --git a/src/core/plan.h b/src/core/plan.h index 0ea86a2..b3038f2 100644 --- a/src/core/plan.h +++ b/src/core/plan.h @@ -3,6 +3,7 @@ #include #include +#include "base/color.h" #include "core/types.h" typedef enum effect_type_t { diff --git a/src/core/runtime.c b/src/core/runtime.c index 2882271..fcca745 100644 --- a/src/core/runtime.c +++ b/src/core/runtime.c @@ -59,6 +59,7 @@ bool runtime_init(runtime_t *runtime, runtime_init_desc_t *desc) { runtime->backend = desc->backend; layout_registry_move(&desc->layouts, &runtime->layouts); rules_move(&desc->rules, &runtime->rules); + runtime->border = desc->border; runtime->config_module_handle = desc->config_module_handle; runtime->binding_table = desc->binding_table; desc->backend = nullptr; diff --git a/src/core/runtime.h b/src/core/runtime.h index bf69e46..7743a5f 100644 --- a/src/core/runtime.h +++ b/src/core/runtime.h @@ -1,7 +1,9 @@ #pragma once #include +#include +#include "base/color.h" #include "core/backend.h" #include "core/binding.h" #include "core/command_buffer.h" @@ -9,6 +11,13 @@ #include "core/plan.h" #include "core/rules.h" #include "core/state.h" +#include "core/types.h" + +typedef struct border_config_t { + uint32_t width; + color_t normal_color; + color_t focused_color; +} border_config_t; typedef struct runtime_init_desc_t { backend_t *backend; @@ -17,6 +26,7 @@ typedef struct runtime_init_desc_t { layout_registry_t layouts; rules_t rules; + border_config_t border; workspace_desc_t *workspaces; size_t workspace_count; void *config_module_handle; @@ -33,6 +43,7 @@ typedef struct runtime_t { layout_result_t layout_result; layout_registry_t layouts; rules_t rules; + border_config_t border; backend_t *backend; void *config_module_handle; binding_table_t *binding_table; diff --git a/src/core/types.h b/src/core/types.h index 782a0bf..255dccd 100644 --- a/src/core/types.h +++ b/src/core/types.h @@ -27,14 +27,6 @@ typedef struct point_t { int32_t y; } point_t; -typedef struct color_t { - uint32_t rgba; - uint32_t argb; - - /* RGBA color channels for Cairo, each channel in the range [0, 1] */ - double red, green, blue, alpha; -} color_t; - typedef enum window_geometry_mode_t { ZDWM_GEOMETRY_NORMAL, ZDWM_GEOMETRY_MAXIMIZED, diff --git a/tests/config/CMakeLists.txt b/tests/config/CMakeLists.txt index 0ac44ef..9fda872 100644 --- a/tests/config/CMakeLists.txt +++ b/tests/config/CMakeLists.txt @@ -37,6 +37,7 @@ add_dependencies(${CONFIG_LOADER_TEST_APP_NAME} add_executable(${RUNTIME_CONFIG_TEST_APP_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/runtime_config_test.c + ${SOURCE_DIR}/base/color.c ${SOURCE_DIR}/base/log.c ${SOURCE_DIR}/config/defaults.c ${SOURCE_DIR}/config/loader.c diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index 904db84..5a20554 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -2,6 +2,7 @@ set(TEST_APP_NAME "zdwm-tests") add_executable(${TEST_APP_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/main.c + ${SOURCE_DIR}/base/color.c ${SOURCE_DIR}/base/log.c ${SOURCE_DIR}/backend/output_utils.c ${SOURCE_DIR}/config/defaults.c