diff --git a/src/config.h b/src/config.h index ade6971..a6312c6 100644 --- a/src/config.h +++ b/src/config.h @@ -60,8 +60,10 @@ const rule_t rules[] = { }; const char *const bar_bg = "#222222"; +const char *const tag_bg = "#222222"; +const char *const active_tag_bg = "#005577"; const char *const tag_color = "#bbbbbb"; -const char *const active_tag_color = "#005577"; +const char *const active_tag_color = "#eeeeee"; const char *const layout_color = "#bbbbbb"; const char *const client_name_color = "#bbbbbb"; const char *const active_client_name_color = "#005577"; diff --git a/src/include/renderer.h b/src/include/renderer.h index 42bea95..817602a 100644 --- a/src/include/renderer.h +++ b/src/include/renderer.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "types.h" @@ -11,4 +12,6 @@ uint32_t *generate_wallpaper(const wallpaper_config_t *wallpaper_config, uint32_t get_font_height(const char *font_family, const uint32_t font_size, const uint32_t dpi); +void draw_bar(monitor_t *monitor, bool is_current_monitor, + color_set_t *color_set, uint32_t height, uint32_t tag_x_padding); void clean_pango_context(void); diff --git a/src/include/types.h b/src/include/types.h index aa7d493..6b57618 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -83,6 +83,8 @@ typedef struct color_t { } color_t; typedef struct color_set_t { color_t bar_bg; + color_t tag_bg; + color_t active_tag_bg; color_t tag_color; color_t active_tag_color; color_t layout_color; diff --git a/src/include/xcb.h b/src/include/xcb.h index 3b634a1..2e65c96 100644 --- a/src/include/xcb.h +++ b/src/include/xcb.h @@ -7,6 +7,7 @@ bool has_other_wm_running(void); int get_xcb_connection_fd(void); +void flush_xcb_connection(void); typedef enum cursor_t { cursor_normal = XC_left_ptr, diff --git a/src/main.c b/src/main.c index 2cef99b..ea9bd32 100644 --- a/src/main.c +++ b/src/main.c @@ -27,12 +27,14 @@ static void init_color_set(void); static void parse_color(const char *hex, color_t *color); static void init_monitor_bar(void); static void get_xresource_config(void); +static void update_bars(void); static void init_xcb_event_loop(void); static gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition, gpointer userdata); static void cleanup(void); static monitor_t *monitors = NULL; +static monitor_t *current_monitor = NULL; static wallpaper_config_t *wallpaper_config = NULL; static color_set_t *color_set = NULL; static GMainLoop *loop = NULL; @@ -64,6 +66,8 @@ static void print_color(const char *prompt, const color_t *color) { } static void print_color_set(color_set_t *set) { print_color("== bar bg:", &set->bar_bg); + print_color("== tag bg:", &set->tag_bg); + print_color("== active tag bg:", &set->active_tag_bg); print_color("== tag color:", &set->tag_color); print_color("== active tag color:", &set->active_tag_color); print_color("== layout bg:", &set->layout_color); @@ -112,6 +116,7 @@ void init_monitors(void) { prev_monitor->next = m; } else { monitors = m; + current_monitor = m; } prev_monitor = m; @@ -122,6 +127,7 @@ void init_monitors(void) { } for (monitor_t *m = monitors; m; m = m->next) { m->tags = get_monitor_tags(i, m->index); + m->selected_tag = 0x1; } } @@ -236,6 +242,8 @@ void free_wallpaper_config(wallpaper_config_t *wallpaper_config) { void init_color_set(void) { color_set = ecalloc(1, sizeof(color_set_t)); char *bar_background = NULL; + char *tag_background = NULL; + char *active_tag_background = NULL; char *tag = NULL; char *active_tag = NULL; char *layout = NULL; @@ -246,6 +254,9 @@ void init_color_set(void) { char *active_border = NULL; get_xresource_string("zswm.color.bar_bg", &bar_background, bar_bg); + get_xresource_string("zswm.color.tag_bg", &tag_background, tag_bg); + get_xresource_string("zswm.color.active_tag_bg", &active_tag_background, + active_tag_bg); get_xresource_string("zswm.color.tag", &tag, tag_color); get_xresource_string("zswm.color.active_tag", &active_tag, active_tag_color); get_xresource_string("zswm.color.layout", &layout, layout_color); @@ -259,6 +270,8 @@ void init_color_set(void) { active_border_color); parse_color(bar_background, &color_set->bar_bg); + parse_color(tag_background, &color_set->tag_bg); + parse_color(active_tag_background, &color_set->active_tag_bg); parse_color(tag, &color_set->tag_color); parse_color(active_tag, &color_set->active_tag_color); parse_color(layout, &color_set->layout_color); @@ -269,6 +282,8 @@ void init_color_set(void) { parse_color(active_border, &color_set->active_border_color); free(bar_background); + free(tag_background); + free(active_tag_background); free(tag); free(active_tag); free(layout); @@ -330,6 +345,13 @@ void get_xresource_config(void) { clean_xresource(); } +void update_bars(void) { + for (monitor_t *m = monitors; m; m = m->next) { + draw_bar(m, m == current_monitor, color_set, bar_height, tag_x_padding); + } + flush_xcb_connection(); +} + void init_xcb_event_loop(void) { GIOChannel *channel = g_io_channel_unix_new(get_xcb_connection_fd()); g_io_channel_set_encoding(channel, NULL, NULL); @@ -392,6 +414,8 @@ int main(int argc, char *argv[]) { set_root_cursor(cursor_normal); init_wallpaper(); + update_bars(); + window_list_t *window_list = scan_window_list(); print_monitor_list_info(monitors); diff --git a/src/renderer/text.c b/src/renderer/text.c index 760669a..b8350ce 100644 --- a/src/renderer/text.c +++ b/src/renderer/text.c @@ -1,4 +1,6 @@ +#include #include +#include #include #include #include @@ -6,12 +8,16 @@ #include #include #include +#include #include #include #include "renderer.h" +#include "types.h" static PangoContext *context = NULL; +static PangoAttrList *attr_list = NULL; +static PangoLayout *layout = NULL; uint32_t get_font_height(const char *font_family, const uint32_t font_size, const uint32_t dpi) { @@ -22,14 +28,13 @@ uint32_t get_font_height(const char *font_family, const uint32_t font_size, pango_cairo_context_set_resolution(context, dpi); PangoLanguage *lang = pango_context_get_language(context); - PangoAttrList *attr_list = pango_attr_list_new(); + attr_list = pango_attr_list_new(); PangoFontDescription *desc = pango_font_description_from_string(font_family); pango_font_description_set_size(desc, font_size * PANGO_SCALE); PangoAttribute *attr = pango_attr_font_desc_new(desc); pango_attr_list_insert(attr_list, attr); - pango_attr_list_unref(attr_list); PangoFontMetrics *metrics = pango_context_get_metrics(context, desc, lang); int ascent = pango_font_metrics_get_ascent(metrics); @@ -43,9 +48,99 @@ uint32_t get_font_height(const char *font_family, const uint32_t font_size, return font_height; } +static void draw_background(cairo_t *cr, color_t *color, int32_t x, int32_t y, + uint32_t width, uint32_t height) { + cairo_move_to(cr, x, y); + cairo_set_source_rgba(cr, color->red, color->green, color->blue, + color->alpha); + cairo_rectangle(cr, x, y, width, height); + cairo_fill(cr); +} + +static void prepare_layout(bool align_center) { + if (!layout) { + layout = pango_layout_new(context); + pango_layout_set_attributes(layout, attr_list); + pango_layout_set_wrap(layout, PANGO_WRAP_NONE); + pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END); + } + + PangoAlignment align = align_center ? PANGO_ALIGN_CENTER : PANGO_ALIGN_LEFT; + pango_layout_set_alignment(layout, align); +} + +static uint32_t get_text_width(const char *text) { + prepare_layout(false); + pango_layout_set_width(layout, -1); + pango_layout_set_text(layout, text, -1); + + int w; + pango_layout_get_pixel_size(layout, &w, NULL); + return (uint32_t)w; +} + +static void draw_text(cairo_t *cr, const char *text, color_t *color, int32_t x, + uint32_t y, uint32_t width, uint32_t height, + bool align_center) { + prepare_layout(align_center); + pango_layout_set_width(layout, width * PANGO_SCALE); + pango_layout_set_text(layout, text, -1); + cairo_set_source_rgba(cr, color->red, color->green, color->blue, + color->alpha); + int h = 0; + pango_layout_get_pixel_size(layout, NULL, &h); + double ty = ((double)height - h) / 2; + + pango_cairo_update_layout(cr, layout); + cairo_move_to(cr, x, y + ty); + pango_cairo_show_layout(cr, layout); +} + +static void clean_cairo_context(cairo_t *cr) { + cairo_save(cr); + cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); + cairo_paint(cr); + cairo_restore(cr); +} + +void draw_bar(monitor_t *monitor, bool is_current_monitor, + color_set_t *color_set, uint32_t height, uint32_t tag_x_padding) { + cairo_t *cr = monitor->cr; + int32_t x = 0; + uint32_t width = 0; + const char *text; + color_t *color; + + clean_cairo_context(cr); + draw_background(cr, &color_set->bar_bg, 0, 0, monitor->monitor_width, height); + + /* 绘制 tags */ + for (int i = 0; i < g_strv_length(monitor->tags); i++) { + bool selected = (monitor->selected_tag >> i) & 0x1; + text = monitor->tags[i]; + width = get_text_width(text) + tag_x_padding * 2; + + color = selected ? &color_set->active_tag_bg : &color_set->tag_bg; + if (color->rgba != color_set->bar_bg.rgba) { + draw_background(cr, color, x, 0, width, height); + } + color = selected ? &color_set->active_tag_color : &color_set->tag_color; + draw_text(cr, text, color, x, 0, width, height, true); + x += width; + } +} + void clean_pango_context(void) { - if (!context) return; - - g_object_unref(context); - context = NULL; + if (layout) { + g_object_unref(layout); + layout = NULL; + } + if (attr_list) { + pango_attr_list_unref(attr_list); + attr_list = NULL; + } + if (context) { + g_object_unref(context); + context = NULL; + } } diff --git a/src/xcb/xcb.c b/src/xcb/xcb.c index 8d162ee..2d64d81 100644 --- a/src/xcb/xcb.c +++ b/src/xcb/xcb.c @@ -54,6 +54,8 @@ bool has_other_wm_running(void) { */ int get_xcb_connection_fd(void) { return xcb_get_file_descriptor(conn); } +void flush_xcb_connection(void) { xcb_flush(conn); } + /* xinerama 扩展是否激活 */ static bool xinerama_active(void) { const char *name = "XINERAMA";