From 2f2a09b41fe8406aa143dbee695596b9962bd361 Mon Sep 17 00:00:00 2001 From: Aki Date: Thu, 9 Sep 2021 21:40:08 +0200 Subject: Moved state to a structure and shifted how it's handled around --- text.c | 157 ++++++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 87 insertions(+), 70 deletions(-) diff --git a/text.c b/text.c index 9daedc0..8ad0d75 100644 --- a/text.c +++ b/text.c @@ -32,21 +32,27 @@ union Command } span; }; -int init_x(void); -void draw_body(cairo_t *); +struct State +{ + int width; + int height; + xcb_connection_t * c; + xcb_screen_t * s; + xcb_visualtype_t * v; + xcb_window_t w; + cairo_t * ctx; + cairo_surface_t * surface; +}; + +int setup(struct State *); +void finalize(struct State *); +int handle(struct State *, xcb_generic_event_t *); +void draw_body(struct State *, union Command *); xcb_visualtype_t * find_visual(xcb_screen_t *); static const int MARGIN = 20; static const char * const FONT = "Serif 16"; -static int width = 800; -static int height = 600; - -static xcb_connection_t * c; -static xcb_screen_t * s; -static xcb_visualtype_t * v; -static xcb_window_t w; - #define _BLOCK(_txt) {.block = {.type = COMMAND_BLOCK, .length = sizeof(_txt) - 1, .data = _txt}} union Command body[] = { {.span = {.type = COMMAND_SPAN, .position = 28, .length = 11}}, @@ -64,73 +70,84 @@ int main(int argc, const char ** argv) { (void) argc; (void) argv; - const int res = init_x(); - if (-1 == res) + struct State state; + if (-1 == setup(&state)) + { + dprintf(2, "Could not connect to X server\n"); // TODO: Helpful (specific) errors. return 1; - cairo_surface_t * surface = cairo_xcb_surface_create(c, w, v, width, height); - cairo_t * ctx = cairo_create(surface); - xcb_map_window(c, w); - xcb_flush(c); - int done = 0; - xcb_generic_event_t * e; - while (!done) + } + for (;;) { - e = xcb_wait_for_event(c); - if (NULL == e) + xcb_generic_event_t * e = xcb_wait_for_event(state.c); // TODO: Change it to poll-like behaviour. + if (handle(&state, e)) break; - switch (XCB_EVENT_RESPONSE_TYPE(e)) - { - default: - break; - case XCB_KEY_PRESS: - done = 1; - break; - case XCB_EXPOSE: - cairo_set_source_rgb(ctx, 1., 1., 1.); - cairo_paint(ctx); - draw_body(ctx); - cairo_surface_flush(surface); - xcb_flush(c); - break; - case XCB_CONFIGURE_NOTIFY: - ; - xcb_configure_notify_event_t * conf = (xcb_configure_notify_event_t *) e; - if (width != conf->width || height != conf->height) - { - cairo_xcb_surface_set_size(surface, conf->width, conf->height); - width = conf->width; - height = conf->height; - } - break; - } - free(e); } - cairo_destroy(ctx); - cairo_surface_destroy(surface); - xcb_disconnect(c); + finalize(&state); } -int init_x(void) +int setup(struct State * state) { - c = xcb_connect(NULL, NULL); - if (xcb_connection_has_error(c)) - { - dprintf(2, "Could not connect to X11 server"); + static const int initial_width = 800; + static const int initial_height = 600; + state->c = xcb_connect(NULL, NULL); + if (xcb_connection_has_error(state->c)) return -1; - } - s = xcb_setup_roots_iterator(xcb_get_setup(c)).data; - w = xcb_generate_id(c); - v = find_visual(s); + state->s = xcb_setup_roots_iterator(xcb_get_setup(state->c)).data; + state->w = xcb_generate_id(state->c); + state->v = find_visual(state->s); const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; const uint32_t values[] = { - s->white_pixel, + state->s->white_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_STRUCTURE_NOTIFY, }; xcb_create_window( - c, XCB_COPY_FROM_PARENT, w, s->root, 0, 0, width, height, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, - s->root_visual, mask, values); - xcb_flush(c); + state->c, XCB_COPY_FROM_PARENT, state->w, state->s->root, 0, 0, initial_width, initial_height, 0, + XCB_WINDOW_CLASS_INPUT_OUTPUT, state->s->root_visual, mask, values); + state->surface = cairo_xcb_surface_create(state->c, state->w, state->v, initial_width, initial_height); + state->ctx = cairo_create(state->surface); + xcb_map_window(state->c, state->w); + xcb_flush(state->c); + return 0; +} + + +void finalize(struct State * state) +{ + cairo_destroy(state->ctx); + cairo_surface_destroy(state->surface); + xcb_disconnect(state->c); +} + + +int handle(struct State * state, xcb_generic_event_t * e) +{ + switch (XCB_EVENT_RESPONSE_TYPE(e)) + { + case XCB_KEY_PRESS: + free(e); + return 1; + case XCB_EXPOSE: + cairo_set_source_rgb(state->ctx, 1., 1., 1.); + cairo_paint(state->ctx); + draw_body(state, body); // TODO: Redraw outside of handler and don't use global body. + cairo_surface_flush(state->surface); + xcb_flush(state->c); + break; + case XCB_CONFIGURE_NOTIFY: + ; + xcb_configure_notify_event_t * conf = (xcb_configure_notify_event_t *) e; + if (state->width != conf->width || state->height != conf->height) + { + cairo_xcb_surface_set_size(state->surface, conf->width, conf->height); + state->width = conf->width; + state->height = conf->height; + } + break; + default: + break; + } + free(e); return 0; } @@ -149,10 +166,10 @@ xcb_visualtype_t * find_visual(xcb_screen_t * screen) } -void draw_body(cairo_t * ctx) +void draw_body(struct State * state, union Command * body) { PangoFontDescription * desc = pango_font_description_from_string(FONT); - cairo_set_source_rgb(ctx, 0., 0., 0.); + cairo_set_source_rgb(state->ctx, 0., 0., 0.); int y = MARGIN; PangoAttrList * attrs = pango_attr_list_new(); // TODO-maybe: Don't recreate attributes lists each redraw? for (union Command * command = body; COMMAND_DONE != command->type; ++command) @@ -167,17 +184,17 @@ void draw_body(cairo_t * ctx) pango_attr_list_change(attrs, attr); break; case COMMAND_BLOCK: - cairo_move_to(ctx, MARGIN, y); - PangoLayout * layout = pango_cairo_create_layout(ctx); + cairo_move_to(state->ctx, MARGIN, y); + PangoLayout * layout = pango_cairo_create_layout(state->ctx); pango_layout_set_attributes(layout, attrs); pango_attr_list_unref(attrs); attrs = pango_attr_list_new(); pango_layout_set_font_description(layout, desc); pango_layout_set_wrap(layout, PANGO_WRAP_WORD); - pango_layout_set_width(layout, (width - 2 * MARGIN) * PANGO_SCALE); + pango_layout_set_width(layout, (state->width - 2 * MARGIN) * PANGO_SCALE); pango_layout_set_text(layout, command->block.data, command->block.length); - pango_cairo_update_layout(ctx, layout); - pango_cairo_show_layout(ctx, layout); + pango_cairo_update_layout(state->ctx, layout); + pango_cairo_show_layout(state->ctx, layout); int height; pango_layout_get_pixel_size(layout, NULL, &height); y += height + MARGIN; -- cgit v1.1