绘制 tag 标识

This commit is contained in:
2025-08-16 04:43:00 +08:00
parent 8472fda46a
commit e87607f817
7 changed files with 145 additions and 7 deletions

View File

@@ -60,8 +60,10 @@ const rule_t rules[] = {
}; };
const char *const bar_bg = "#222222"; 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 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 layout_color = "#bbbbbb";
const char *const client_name_color = "#bbbbbb"; const char *const client_name_color = "#bbbbbb";
const char *const active_client_name_color = "#005577"; const char *const active_client_name_color = "#005577";

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include "types.h" #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, uint32_t get_font_height(const char *font_family, const uint32_t font_size,
const uint32_t dpi); 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); void clean_pango_context(void);

View File

@@ -83,6 +83,8 @@ typedef struct color_t {
} color_t; } color_t;
typedef struct color_set_t { typedef struct color_set_t {
color_t bar_bg; color_t bar_bg;
color_t tag_bg;
color_t active_tag_bg;
color_t tag_color; color_t tag_color;
color_t active_tag_color; color_t active_tag_color;
color_t layout_color; color_t layout_color;

View File

@@ -7,6 +7,7 @@
bool has_other_wm_running(void); bool has_other_wm_running(void);
int get_xcb_connection_fd(void); int get_xcb_connection_fd(void);
void flush_xcb_connection(void);
typedef enum cursor_t { typedef enum cursor_t {
cursor_normal = XC_left_ptr, cursor_normal = XC_left_ptr,

View File

@@ -27,12 +27,14 @@ static void init_color_set(void);
static void parse_color(const char *hex, color_t *color); static void parse_color(const char *hex, color_t *color);
static void init_monitor_bar(void); static void init_monitor_bar(void);
static void get_xresource_config(void); static void get_xresource_config(void);
static void update_bars(void);
static void init_xcb_event_loop(void); static void init_xcb_event_loop(void);
static gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition, static gboolean handle_xcb_event(GIOChannel *channel, GIOCondition condition,
gpointer userdata); gpointer userdata);
static void cleanup(void); static void cleanup(void);
static monitor_t *monitors = NULL; static monitor_t *monitors = NULL;
static monitor_t *current_monitor = NULL;
static wallpaper_config_t *wallpaper_config = NULL; static wallpaper_config_t *wallpaper_config = NULL;
static color_set_t *color_set = NULL; static color_set_t *color_set = NULL;
static GMainLoop *loop = 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) { static void print_color_set(color_set_t *set) {
print_color("== bar bg:", &set->bar_bg); 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("== tag color:", &set->tag_color);
print_color("== active tag color:", &set->active_tag_color); print_color("== active tag color:", &set->active_tag_color);
print_color("== layout bg:", &set->layout_color); print_color("== layout bg:", &set->layout_color);
@@ -112,6 +116,7 @@ void init_monitors(void) {
prev_monitor->next = m; prev_monitor->next = m;
} else { } else {
monitors = m; monitors = m;
current_monitor = m;
} }
prev_monitor = m; prev_monitor = m;
@@ -122,6 +127,7 @@ void init_monitors(void) {
} }
for (monitor_t *m = monitors; m; m = m->next) { for (monitor_t *m = monitors; m; m = m->next) {
m->tags = get_monitor_tags(i, m->index); 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) { void init_color_set(void) {
color_set = ecalloc(1, sizeof(color_set_t)); color_set = ecalloc(1, sizeof(color_set_t));
char *bar_background = NULL; char *bar_background = NULL;
char *tag_background = NULL;
char *active_tag_background = NULL;
char *tag = NULL; char *tag = NULL;
char *active_tag = NULL; char *active_tag = NULL;
char *layout = NULL; char *layout = NULL;
@@ -246,6 +254,9 @@ void init_color_set(void) {
char *active_border = NULL; char *active_border = NULL;
get_xresource_string("zswm.color.bar_bg", &bar_background, bar_bg); 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.tag", &tag, tag_color);
get_xresource_string("zswm.color.active_tag", &active_tag, active_tag_color); get_xresource_string("zswm.color.active_tag", &active_tag, active_tag_color);
get_xresource_string("zswm.color.layout", &layout, layout_color); get_xresource_string("zswm.color.layout", &layout, layout_color);
@@ -259,6 +270,8 @@ void init_color_set(void) {
active_border_color); active_border_color);
parse_color(bar_background, &color_set->bar_bg); 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(tag, &color_set->tag_color);
parse_color(active_tag, &color_set->active_tag_color); parse_color(active_tag, &color_set->active_tag_color);
parse_color(layout, &color_set->layout_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); parse_color(active_border, &color_set->active_border_color);
free(bar_background); free(bar_background);
free(tag_background);
free(active_tag_background);
free(tag); free(tag);
free(active_tag); free(active_tag);
free(layout); free(layout);
@@ -330,6 +345,13 @@ void get_xresource_config(void) {
clean_xresource(); 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) { void init_xcb_event_loop(void) {
GIOChannel *channel = g_io_channel_unix_new(get_xcb_connection_fd()); GIOChannel *channel = g_io_channel_unix_new(get_xcb_connection_fd());
g_io_channel_set_encoding(channel, NULL, NULL); g_io_channel_set_encoding(channel, NULL, NULL);
@@ -392,6 +414,8 @@ int main(int argc, char *argv[]) {
set_root_cursor(cursor_normal); set_root_cursor(cursor_normal);
init_wallpaper(); init_wallpaper();
update_bars();
window_list_t *window_list = scan_window_list(); window_list_t *window_list = scan_window_list();
print_monitor_list_info(monitors); print_monitor_list_info(monitors);

View File

@@ -1,4 +1,6 @@
#include <cairo.h>
#include <glib-object.h> #include <glib-object.h>
#include <glib.h>
#include <pango/pango-attributes.h> #include <pango/pango-attributes.h>
#include <pango/pango-context.h> #include <pango/pango-context.h>
#include <pango/pango-font.h> #include <pango/pango-font.h>
@@ -6,12 +8,16 @@
#include <pango/pango-layout.h> #include <pango/pango-layout.h>
#include <pango/pango-types.h> #include <pango/pango-types.h>
#include <pango/pangocairo.h> #include <pango/pangocairo.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include "renderer.h" #include "renderer.h"
#include "types.h"
static PangoContext *context = NULL; 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, uint32_t get_font_height(const char *font_family, const uint32_t font_size,
const uint32_t dpi) { 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); pango_cairo_context_set_resolution(context, dpi);
PangoLanguage *lang = pango_context_get_language(context); 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); PangoFontDescription *desc = pango_font_description_from_string(font_family);
pango_font_description_set_size(desc, font_size * PANGO_SCALE); pango_font_description_set_size(desc, font_size * PANGO_SCALE);
PangoAttribute *attr = pango_attr_font_desc_new(desc); PangoAttribute *attr = pango_attr_font_desc_new(desc);
pango_attr_list_insert(attr_list, attr); pango_attr_list_insert(attr_list, attr);
pango_attr_list_unref(attr_list);
PangoFontMetrics *metrics = pango_context_get_metrics(context, desc, lang); PangoFontMetrics *metrics = pango_context_get_metrics(context, desc, lang);
int ascent = pango_font_metrics_get_ascent(metrics); int ascent = pango_font_metrics_get_ascent(metrics);
@@ -43,9 +48,108 @@ uint32_t get_font_height(const char *font_family, const uint32_t font_size,
return font_height; 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 void get_layout_size(PangoLayout *layout, int *width, int *height) {
PangoRectangle ink_rect, logical_rect;
pango_layout_get_pixel_extents(layout, &ink_rect, &logical_rect);
int w = MAX(ink_rect.width, logical_rect.width);
int h = MAX(ink_rect.height, logical_rect.height);
if (width) *width = w;
if (height) *height = h;
}
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;
get_layout_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;
get_layout_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) { void clean_pango_context(void) {
if (!context) return; if (layout) {
g_object_unref(layout);
g_object_unref(context); layout = NULL;
context = NULL; }
if (attr_list) {
pango_attr_list_unref(attr_list);
attr_list = NULL;
}
if (context) {
g_object_unref(context);
context = NULL;
}
} }

View File

@@ -54,6 +54,8 @@ bool has_other_wm_running(void) {
*/ */
int get_xcb_connection_fd(void) { return xcb_get_file_descriptor(conn); } int get_xcb_connection_fd(void) { return xcb_get_file_descriptor(conn); }
void flush_xcb_connection(void) { xcb_flush(conn); }
/* xinerama 扩展是否激活 */ /* xinerama 扩展是否激活 */
static bool xinerama_active(void) { static bool xinerama_active(void) {
const char *name = "XINERAMA"; const char *name = "XINERAMA";