#include #include #include #include #include #include #include #include #include #include "pipe.h" #include "bardata.h" Display* display; Window win; GC gc; XftFont* font = NULL; static int bar_width = 1000; static float width_ratio = 1; static int err_code = 1; void die(const char* fmt, ...) { va_list args; va_start(args, fmt); vfprintf(stderr, fmt, args); va_end(args); putc('\n', stderr); exit(err_code); } size_t utf8_strlen(const char *s) { size_t len = 0; while (*s) { if ((*s & 0xC0) != 0x80) len++; s++; } return len; } void load_font(const char* font_name) { XftFont* new_font = XftFontOpenName(display, DefaultScreen(display), font_name); if (new_font == NULL) { fprintf(stderr, "cannot open font %s\n", font_name); return; } if (font != NULL) { XftFontClose(display, font); } font = new_font; } void init_x(void) { display = XOpenDisplay(NULL); if (display == NULL) { die("could not open X display"); } XSetWindowAttributes win_attr = { .override_redirect = 1, .background_pixel = 0x202020, .event_mask = ExposureMask | PropertyChangeMask, }; Screen* screen = DefaultScreenOfDisplay(display); bar_width = WidthOfScreen(screen); win = XCreateWindow( display, DefaultRootWindow(display), 0, 0, bar_width, bar_height, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect | CWBackPixel | CWEventMask, &win_attr ); XClassHint class_hint; class_hint.res_name = "tsarbar"; class_hint.res_class = "Bar"; XSetClassHint(display, win, &class_hint); XMapWindow(display, win); load_font("monospace:size=10"); gc = XCreateGC(display, win, 0, NULL); XSetForeground(display, gc, 0xFFFFFF); XLowerWindow(display, win); XFlush(display); } void deinit_x(void) { XftFontClose(display, font); XUnmapWindow(display, win); XDestroyWindow(display, win); } void draw_text( const char* text, int x, int y, const XftColor* fg_color, const XftColor* bg_color ) { XftDraw* xft_draw = XftDrawCreate( display, win, DefaultVisual(display, DefaultScreen(display)), DefaultColormap(display, DefaultScreen(display)) ); size_t width = font->max_advance_width * utf8_strlen(text); XftDrawRect(xft_draw, bg_color, x, y, width, bar_height); int dy = y + (bar_height - font->height) / 2 + font->ascent; XftDrawStringUtf8(xft_draw, fg_color, font, x, dy, (const FcChar8*)text, strlen(text)); XftDrawDestroy(xft_draw); } void draw_comp_set(float pos_ratio, comp_t **set, int size) { int width = (size - 1) * comp_gap; for (int i = 0; i < size; i++) { comp_t *comp = set[i]; width += font->max_advance_width * utf8_strlen(comp->data); } int x = (bar_width - width) * pos_ratio; x += padding * 2*(0.5 - pos_ratio); // Magic formula lol int y = 0;//(bar_height - font->height) / 2; for (int i = 0; i < size; i++) { comp_t *comp = set[i]; draw_text(comp->data, x, y, comp->fg, comp->bg); x += font->max_advance_width * utf8_strlen(comp->data); x += comp_gap; } } int main(void) { init_pipe(); init_x(); init_bardata(); while (true) { XEvent ev; while (XPending(display)) XNextEvent(display, &ev); XClearWindow(display, win); XResizeWindow(display, win, bar_width, bar_height); draw_comp_set(0, comps_left, left_size); draw_comp_set(0.5, comps_center, center_size); draw_comp_set(1, comps_right, right_size); XFlush(display); await_change(); } deinit_x(); return 0; }