diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 88d69fb..9fd169f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,15 @@ project(${APP_NAME} LANGUAGES C ) -add_executable(${APP_NAME} wm.c utils.c buffer.c backtrace.c monitor.c client.c) +add_executable(${APP_NAME} + wm.c + utils.c + buffer.c + backtrace.c + monitor.c + client.c + text.c +) # use C23 set_property(TARGET ${APP_NAME} PROPERTY C_STANDARD 23) @@ -34,6 +42,9 @@ pkg_check_modules(deps REQUIRED xcb-randr xcb-xfixes xcb-xinerama + + pango + pangocairo ) target_include_directories(${APP_NAME} SYSTEM diff --git a/src/default_config.h b/src/default_config.h index 42b9018..7c414a4 100644 --- a/src/default_config.h +++ b/src/default_config.h @@ -1,3 +1,6 @@ +#include + static const char *const tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", nullptr, }; +static const uint32_t bar_y_padding = 1; diff --git a/src/draw.h b/src/draw.h deleted file mode 100644 index 45dcbb0..0000000 --- a/src/draw.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - - diff --git a/src/text.c b/src/text.c new file mode 100644 index 0000000..a4b81ae --- /dev/null +++ b/src/text.c @@ -0,0 +1,92 @@ +#include "text.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static PangoContext *context = nullptr; +static PangoLayout *layout = nullptr; +static PangoAttrList *attr_list = nullptr; + +/** + * 初始化绘制文字的 pango 环境 + * @param family 多个字体用逗号分割 + * @param size 字体大小 + * @param dpi + * @return layout 高度,可用于确定 bar 高度 + */ +int text_init_pango_layout(const char *family, uint32_t size, uint32_t dpi) { + static const char *layout_family = nullptr; + static uint32_t layout_size = 0; + static uint32_t layout_dpi = 0; + static int text_height = 0; + + if (layout_family != nullptr && strcmp(layout_family, family) == 0 && + layout_size == size && layout_dpi == dpi) { + printf("text pango layout config cached\n"); + return text_height; + } + + text_clean_pango_layout(); + + layout_family = family; + layout_size = size; + layout_dpi = dpi; + + PangoFontMap *fontmap = pango_cairo_font_map_new(); + context = pango_font_map_create_context(fontmap); + pango_cairo_context_set_resolution(context, (double)dpi); + + layout = pango_layout_new(context); + + PangoFontDescription *desc = pango_font_description_from_string(family); + pango_font_description_set_size(desc, size * PANGO_SCALE); + PangoLanguage *lang = pango_context_get_language(context); + PangoFontMetrics *metrics = pango_context_get_metrics(context, desc, lang); + + PangoAttribute *attr = pango_attr_font_desc_new(desc); + attr_list = pango_attr_list_new(); + pango_attr_list_insert(attr_list, attr); + + int height = pango_font_metrics_get_height(metrics); + int ascent = pango_font_metrics_get_ascent(metrics); + int descent = pango_font_metrics_get_descent(metrics); + text_height = + MAX(PANGO_PIXELS_CEIL(height), PANGO_PIXELS_CEIL(ascent + descent)); + + pango_font_metrics_unref(metrics); + pango_font_description_free(desc); + g_object_unref(fontmap); + + PangoRectangle ink_rect, logical_rect; + pango_layout_get_pixel_extents(layout, &ink_rect, &logical_rect); + + text_height = MAX(text_height, MAX(ink_rect.height, logical_rect.height)); + + return text_height; +} + +void text_clean_pango_layout(void) { + if (attr_list) { + pango_attr_list_unref(attr_list); + attr_list = nullptr; + } + + if (layout) { + g_object_unref(layout); + layout = nullptr; + } + + if (context) { + g_object_unref(context); + context = nullptr; + } +} diff --git a/src/text.h b/src/text.h new file mode 100644 index 0000000..9c3fda7 --- /dev/null +++ b/src/text.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +int text_init_pango_layout(const char *family, uint32_t size, uint32_t dpi); +void text_clean_pango_layout(void); diff --git a/src/wm.c b/src/wm.c index 9a00794..849510d 100644 --- a/src/wm.c +++ b/src/wm.c @@ -20,6 +20,7 @@ #include "buffer.h" #include "default_config.h" #include "monitor.h" +#include "text.h" #include "types.h" #include "utils.h" @@ -257,6 +258,11 @@ void wm_clean(void) { } static void wm_setup(void) { + int font_height = text_init_pango_layout("Terminus, Emacs Simsun", 10, 144); + wm.bar_height = (uint32_t)font_height + 2 * bar_y_padding; + + printf("font height: %d, bar height: %u\n", font_height, wm.bar_height); + for (monitor_t *m = wm.monitor_list; m; m = m->next) { monitor_initialize_tag(m, (const char **)tags); } diff --git a/src/wm.h b/src/wm.h index 7f9a29e..3378292 100644 --- a/src/wm.h +++ b/src/wm.h @@ -1,8 +1,12 @@ #pragma once +#include + #include "types.h" typedef struct wm_t { + uint32_t bar_height; + bool need_restart; GMainLoop *loop;