#include #include #include #include #include #include #include #include "window.h" #include "log.h" #include "draw.h" #include "connect.h" #include "state.h" #define EVEN(n) ((int)(n) - ((int)(n) % 2 != 0)) static void log_handler(const char *log_domain, GLogLevelFlags level, const char *message, gpointer log_level) { GLogLevelFlags message_level = level & G_LOG_LEVEL_MASK; if ((GLogLevelFlags)log_level < message_level) return; if (message_level <= G_LOG_LEVEL_WARNING) g_printerr("%s\n", message); else g_print("%s\n", message); } static gboolean mainloop_quit(gpointer data) { g_main_loop_quit(data); return G_SOURCE_CONTINUE; } static gboolean disk_update(gpointer data) { Button *btn = data; struct statvfs buffer; g_assert(statvfs("/", &buffer) == 0); const double total = buffer.f_blocks * buffer.f_frsize; const double available = buffer.f_bfree * buffer.f_frsize; const double used = total - available; g_free(btn->text); btn->text = g_strdup_printf(" %d%%", (int)round((used / total) * 100.0)); log_debug("Updated disk percentage"); state_redraw(btn->action_data); return G_SOURCE_CONTINUE; } static gboolean date_update(gpointer data) { Button *btn = data; g_free(btn->text); GDateTime *time = g_date_time_new_now_local(); char *date = g_date_time_format(time, "%A %d %H:%M"); g_assert(date != NULL); btn->text = date; struct { State *state; timer_t timer; } *date_ctx = btn->action_data; log_debug("Updated date and time"); state_redraw(date_ctx->state); struct timespec current; clock_gettime(CLOCK_REALTIME, ¤t); struct itimerspec its = { 0 }; its.it_value.tv_sec = 60 - (current.tv_sec % 60); timer_settime(date_ctx->timer, 0, &its, NULL); return G_SOURCE_CONTINUE; } static void show_action(Button *btn) { log_info("Called action: %s", btn->text); } static void quit_action(Button *btn) { log_info("Quit button pressed"); g_main_loop_quit(btn->action_data); } int main(int argc, char **argv) { setlocale(LC_CTYPE, ""); g_log_set_default_handler(log_handler, (gpointer)G_LOG_LEVEL_DEBUG); GMainLoop *mainloop = g_main_loop_new(NULL, FALSE); Connection *con = connect_create(); Window *win = window_create(con); int screen_width = con->screen_size->width; int screen_height = con->screen_size->height; int height = EVEN(round(screen_height * 0.021)); int x_padding = EVEN(round(screen_width * 0.005)); int y_padding = EVEN(round(screen_height * 0.004)); log_debug("Calculated dimensions [height=%d, x_pad=%d, y_pad=%d]", height, x_padding, y_padding); Color background_all = { 0.3, 0.3, 0.3, 1 }; Drawable *draw = draw_create("Hack 13 Bold", height, x_padding, x_padding, y_padding, 0); draw_set_background(draw, background_all); State *state = state_create(win, draw); Color background = { 0.4, 0.4, 0.4, 1 }; Color foreground = { 0.8, 0.8, 0.8, 1 }; Color stroke = { 0.8, 0.8, 0.8, 1 }; for (int i = 0; i < 9; ++i) { char text[] = { '1' + i, '\0' }; Button *btn = button_create(text, PANGO_ALIGN_LEFT); button_set_colors(btn, background, foreground, stroke); button_set_action(btn, show_action, NULL); state_add_button(state, btn); } Button *disk_btn = button_create("disk", PANGO_ALIGN_RIGHT); button_set_colors(disk_btn, background, foreground, stroke); button_set_action(disk_btn, show_action, state); state_add_button(state, disk_btn); disk_update(disk_btn); g_timeout_add(60 * 1000, disk_update, disk_btn); struct { State *state; timer_t timer; } date_ctx = { state, 0 }; Button *date_btn = button_create("date", PANGO_ALIGN_CENTER); button_set_colors(date_btn, background, foreground, stroke); button_set_action(date_btn, show_action, &date_ctx); state_add_button(state, date_btn); struct sigevent sev = { 0 }; sev.sigev_notify = SIGEV_SIGNAL; sev.sigev_signo = SIGUSR1; g_assert(timer_create(CLOCK_REALTIME, &sev, &date_ctx.timer) == 0); date_update(date_btn); // purple Color background2 = { 0.502, 0.168, 0.886, 1 }; Button *q_btn = button_create("Q", PANGO_ALIGN_RIGHT); button_set_colors(q_btn, background2, foreground, stroke); button_set_action(q_btn, quit_action, mainloop); state_add_button(state, q_btn); connect_attach_state(con, state); connect_attach_source(con); guint source_alrm = g_unix_signal_add(SIGUSR1, date_update, date_btn); guint source_term = g_unix_signal_add(SIGTERM, mainloop_quit, mainloop); guint source_int = g_unix_signal_add(SIGINT, mainloop_quit, mainloop); state_redraw(state); log_debug("Starting main loop"); g_main_loop_run(mainloop); log_debug("Cleaning main loop"); g_clear_pointer(&mainloop, g_main_loop_unref); g_source_remove(source_alrm); g_source_remove(source_term); g_source_remove(source_int); timer_delete(date_ctx.timer); state_destroy(state); draw_destroy(draw); window_destroy(win); return 0; } // vim: ts=4 sw=4 et