#include "bar/config.h" #include "bar/event.h" #include "bar/modules.h" #include "bar/platform.h" #include "bar/renderer.h" #include "bar/util.h" #include #include #include #include static module_t *modules[MODULE_COUNT]; void drain_and_reload(void); typedef struct { platform_t *platform; renderer_t *renderer; dbus_ctx_t *dbus; bool dirty; } bar_t; static bar_t bar; static void schedule_redraw(void *data) { bar_t *b = data; b->dirty = true; } static void do_render(void *data) { bar_t *bar = data; if (!bar->dirty) return; bar->dirty = false; segment_t segs[MAX_SEGMENTS_PER_MODULE * MODULE_COUNT]; size_t count = 0; for (size_t i = 0; i < MODULE_COUNT; i++) { if (!modules[i]) continue; segment_t module_segs[16]; size_t n = modules[i]->render(modules[i], module_segs); if (n > MAX_SEGMENTS_PER_MODULE) n = MAX_SEGMENTS_PER_MODULE; for (size_t j = 0; j < n; j++) { module_segs[j].module_id = (int)i; module_segs[j].seg_id = (int)j; segs[count++] = module_segs[j]; } } bool animating = renderer_draw(bar->renderer, bar->platform, segs, count); if (animating) bar->dirty = true; } static void wl_io_fn(int fd, uint32_t events, void *data) { (void)fd; (void)events; platform_dispatch(data); } static void config_io_fn(int fd, uint32_t events, void *data) { (void)fd; (void)events; bar_t *b = data; drain_and_reload(); b->dirty = true; } static void tick_animations(void *data) { bar_t *b = data; if (config_update(1.0f / 33.0f)) b->dirty = true; } static void sig_handler(int sig) { (void)sig; event_loop_stop(); } static void bar_destroy() { for (size_t i = 0; i < MODULE_COUNT; i++) { if (modules[i]) { if (modules[i]->destroy) modules[i]->destroy(modules[i]); modules[i] = nullptr; } } } int main(void) { setlocale(LC_ALL, ""); struct sigaction sa = { .sa_handler = sig_handler, }; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, nullptr); sigaction(SIGTERM, &sa, nullptr); if (!event_loop_init()) { crit("failed to initialise event loop"); return 1; } config_init(); platform_t *pf = platform_init(); if (!pf) { crit("failed to initialise platform"); return event_loop_destroy(), 1; } bar.platform = pf; renderer_t *rnd = renderer_init(MODULE_COUNT * MAX_SEGMENTS_PER_MODULE); if (!rnd) { crit("failed to initialise renderer"); platform_destroy(pf); return event_loop_destroy(), 1; } bar.renderer = rnd; if (!event_loop_add_io(platform_get_fd(pf), EVENT_READ, wl_io_fn, pf)) { crit("failed to add wayland fd to event loop"); platform_destroy(pf); event_loop_destroy(); return 1; } bar.dbus = dbus_ctx_new(); if (!bar.dbus) warn("failed to initialise shared d-bus context"); int conf_fd = config_get_inotify_fd(); if (conf_fd >= 0) { if (!event_loop_add_io(conf_fd, EVENT_READ, config_io_fn, &bar)) warn("failed to add config inotify fd to event loop"); } event_loop_add_timer(33, true, tick_animations, &bar); protocol_t *proto = protocol_detect(); if (g_config.window_enabled) modules[0] = window_module_new(proto, schedule_redraw, &bar); else warn("failed to initialise window module"); if (g_config.media_enabled) modules[1] = media_module_new(bar.dbus, schedule_redraw, &bar); else warn("failed to initialise media module"); if (g_config.workspaces_enabled) modules[2] = workspaces_module_new(proto, schedule_redraw, &bar); else warn("failed to initialise workspaces module"); if (g_config.clock_enabled) modules[3] = clock_module_new(schedule_redraw, &bar); else warn("failed to initialise clock module"); schedule_redraw(&bar); event_loop_set_idle(do_render, &bar); event_loop_run(); bar_destroy(); if (bar.dbus) dbus_ctx_destroy(bar.dbus); protocol_destroy(proto); config_destroy(); renderer_destroy(rnd); platform_destroy(pf); event_loop_destroy(); return 0; }