diff options
Diffstat (limited to 'swaybar')
-rw-r--r-- | swaybar/bar.c | 112 | ||||
-rw-r--r-- | swaybar/event_loop.c | 4 | ||||
-rw-r--r-- | swaybar/i3bar.c | 216 | ||||
-rw-r--r-- | swaybar/render.c | 33 | ||||
-rw-r--r-- | swaybar/status_line.c | 148 |
5 files changed, 311 insertions, 202 deletions
diff --git a/swaybar/bar.c b/swaybar/bar.c index 3ae730f7..69069f40 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -48,8 +48,13 @@ static void swaybar_output_free(struct swaybar_output *output) { return; } wlr_log(WLR_DEBUG, "Removing output %s", output->name); - zwlr_layer_surface_v1_destroy(output->layer_surface); - wl_surface_destroy(output->surface); + if (output->layer_surface != NULL) { + zwlr_layer_surface_v1_destroy(output->layer_surface); + } + if (output->surface != NULL) { + wl_surface_destroy(output->surface); + } + zxdg_output_v1_destroy(output->xdg_output); wl_output_destroy(output->output); destroy_buffer(&output->buffers[0]); destroy_buffer(&output->buffers[1]); @@ -283,6 +288,37 @@ const struct wl_seat_listener seat_listener = { .name = seat_handle_name, }; +static void add_layer_surface(struct swaybar_output *output) { + if (output->surface != NULL) { + return; + } + struct swaybar *bar = output->bar; + + output->surface = wl_compositor_create_surface(bar->compositor); + assert(output->surface); + output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( + bar->layer_shell, output->surface, output->output, + ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); + assert(output->layer_surface); + zwlr_layer_surface_v1_add_listener(output->layer_surface, + &layer_surface_listener, output); + zwlr_layer_surface_v1_set_anchor(output->layer_surface, + bar->config->position); +} + +static bool bar_uses_output(struct swaybar *bar, const char *name) { + if (bar->config->all_outputs) { + return true; + } + struct config_output *coutput; + wl_list_for_each(coutput, &bar->config->outputs, link) { + if (strcmp(coutput->name, name) == 0) { + return true; + } + } + return false; +} + static void output_geometry(void *data, struct wl_output *output, int32_t x, int32_t y, int32_t width_mm, int32_t height_mm, int32_t subpixel, const char *make, const char *model, int32_t transform) { @@ -326,7 +362,22 @@ static void xdg_output_handle_logical_size(void *data, static void xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output) { - // Who cares + struct swaybar_output *output = data; + struct swaybar *bar = output->bar; + + assert(output->name != NULL); + if (!bar_uses_output(bar, output->name)) { + swaybar_output_free(output); + return; + } + + if (wl_list_empty(&output->link)) { + wl_list_remove(&output->link); + wl_list_insert(&bar->outputs, &output->link); + + add_layer_surface(output); + render_frame(bar, output); + } } static void xdg_output_handle_name(void *data, @@ -349,17 +400,15 @@ struct zxdg_output_v1_listener xdg_output_listener = { .description = xdg_output_handle_description, }; -static bool bar_uses_output(struct swaybar *bar, const char *name) { - if (bar->config->all_outputs) { - return true; - } - struct config_output *coutput; - wl_list_for_each(coutput, &bar->config->outputs, link) { - if (strcmp(coutput->name, name) == 0) { - return true; - } +static void add_xdg_output(struct swaybar_output *output) { + if (output->xdg_output != NULL) { + return; } - return false; + assert(output->bar->xdg_output_manager != NULL); + output->xdg_output = zxdg_output_manager_v1_get_xdg_output( + output->bar->xdg_output_manager, output->output); + zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, + output); } static void handle_global(void *data, struct wl_registry *registry, @@ -386,7 +435,10 @@ static void handle_global(void *data, struct wl_registry *registry, output->wl_name = name; wl_list_init(&output->workspaces); wl_list_init(&output->hotspots); - wl_list_insert(&bar->outputs, &output->link); + wl_list_init(&output->link); + if (bar->xdg_output_manager != NULL) { + add_xdg_output(output); + } } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { bar->layer_shell = wl_registry_bind( registry, name, &zwlr_layer_shell_v1_interface, 1); @@ -416,7 +468,9 @@ static const struct wl_registry_listener registry_listener = { static void render_all_frames(struct swaybar *bar) { struct swaybar_output *output; wl_list_for_each(output, &bar->outputs, link) { - render_frame(bar, output); + if (output->surface != NULL) { + render_frame(bar, output); + } } } @@ -443,23 +497,10 @@ void bar_setup(struct swaybar *bar, struct swaybar_output *output; wl_list_for_each(output, &bar->outputs, link) { - output->xdg_output = zxdg_output_manager_v1_get_xdg_output( - bar->xdg_output_manager, output->output); - zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, - output); + add_xdg_output(output); } wl_display_roundtrip(bar->display); - struct swaybar_output *output_tmp; - wl_list_for_each_safe(output, output_tmp, &bar->outputs, link) { - if (!bar_uses_output(bar, output->name)) { - zxdg_output_v1_destroy(output->xdg_output); - wl_output_destroy(output->output); - wl_list_remove(&output->link); - free(output); - } - } - struct swaybar_pointer *pointer = &bar->pointer; int max_scale = 1; @@ -479,18 +520,6 @@ void bar_setup(struct swaybar *bar, pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); assert(pointer->cursor_surface); - wl_list_for_each(output, &bar->outputs, link) { - output->surface = wl_compositor_create_surface(bar->compositor); - assert(output->surface); - output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( - bar->layer_shell, output->surface, output->output, - ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); - assert(output->layer_surface); - zwlr_layer_surface_v1_add_listener(output->layer_surface, - &layer_surface_listener, output); - zwlr_layer_surface_v1_set_anchor(output->layer_surface, - bar->config->position); - } ipc_get_workspaces(bar); render_all_frames(bar); } @@ -529,6 +558,7 @@ void bar_run(struct swaybar *bar) { } while (1) { event_loop_poll(); + wl_display_flush(bar->display); } } diff --git a/swaybar/event_loop.c b/swaybar/event_loop.c index bc4053be..686b9962 100644 --- a/swaybar/event_loop.c +++ b/swaybar/event_loop.c @@ -105,7 +105,7 @@ bool remove_timer(timer_t timer) { return false; } -void event_loop_poll() { +void event_loop_poll(void) { poll(event_loop.fds.items, event_loop.fds.length, -1); for (int i = 0; i < event_loop.fds.length; ++i) { @@ -146,7 +146,7 @@ void event_loop_poll() { } } -void init_event_loop() { +void init_event_loop(void) { event_loop.fds.length = 0; event_loop.fds.capacity = 10; event_loop.fds.items = malloc( diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 0becae5d..325aa61a 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c @@ -1,6 +1,7 @@ #define _POSIX_C_SOURCE 200809L #include <json-c/json.h> #include <linux/input-event-codes.h> +#include <ctype.h> #include <stdlib.h> #include <string.h> #include <unistd.h> @@ -24,24 +25,19 @@ void i3bar_block_unref(struct i3bar_block *block) { } } -static bool i3bar_parse_json(struct status_line *status, const char *text) { +static void i3bar_parse_json(struct status_line *status, + struct json_object *json_array) { struct i3bar_block *block, *tmp; wl_list_for_each_safe(block, tmp, &status->blocks, link) { wl_list_remove(&block->link); i3bar_block_unref(block); } - json_object *results = json_tokener_parse(text); - if (!results) { - status_error(status, "[failed to parse i3bar json]"); - return false; - } - wlr_log(WLR_DEBUG, "Got i3bar json: '%s'", text); - for (size_t i = 0; i < json_object_array_length(results); ++i) { + for (size_t i = 0; i < json_object_array_length(json_array); ++i) { json_object *full_text, *short_text, *color, *min_width, *align, *urgent; json_object *name, *instance, *separator, *separator_block_width; json_object *background, *border, *border_top, *border_bottom; json_object *border_left, *border_right, *markup; - json_object *json = json_object_array_get_idx(results, i); + json_object *json = json_object_array_get_idx(json_array, i); if (!json) { continue; } @@ -110,96 +106,160 @@ static bool i3bar_parse_json(struct status_line *status, const char *text) { json_object_get_int(border_right) : 1; wl_list_insert(&status->blocks, &block->link); } - json_object_put(results); - return true; } bool i3bar_handle_readable(struct status_line *status) { - struct i3bar_protocol_state *state = &status->i3bar_state; - - char *cur = &state->buffer[state->buffer_index]; - ssize_t n = read(status->read_fd, cur, - state->buffer_size - state->buffer_index); - if (n == -1) { - status_error(status, "[failed to read from status command]"); - return false; - } + while (!status->started) { // look for opening bracket + for (size_t c = 0; c < status->buffer_index; ++c) { + if (status->buffer[c] == '[') { + status->started = true; + status->buffer_index -= ++c; + memmove(status->buffer, &status->buffer[c], status->buffer_index); + break; + } else if (!isspace(status->buffer[c])) { + wlr_log(WLR_DEBUG, "Invalid i3bar json: expected '[' but encountered '%c'", + status->buffer[c]); + status_error(status, "[invalid i3bar json]"); + return true; + } + } + if (status->started) { + break; + } - if (n == (ssize_t)(state->buffer_size - state->buffer_index)) { - state->buffer_size = state->buffer_size * 2; - char *new_buffer = realloc(state->buffer, state->buffer_size); - if (!new_buffer) { - free(state->buffer); - status_error(status, "[failed to allocate buffer]"); + errno = 0; + ssize_t read_bytes = read(status->read_fd, status->buffer, status->buffer_size); + if (read_bytes > -1) { + status->buffer_index = read_bytes; + } else if (errno == EAGAIN) { + return false; + } else { + status_error(status, "[error reading from status command]"); return true; } - state->current_node += new_buffer - state->buffer; - cur += new_buffer - state->buffer; - state->buffer = new_buffer; } - cur[n] = '\0'; - bool redraw = false; - while (*cur) { - if (state->nodes[state->depth] == JSON_NODE_STRING) { - if (!state->escape && *cur == '"') { - --state->depth; + struct json_object *last_object = NULL; + struct json_object *test_object; + size_t buffer_pos = 0; + while (true) { + // since the incoming stream is an infinite array + // parsing is split into two parts + // first, attempt to parse the current object, reading more if the + // parser indicates that the current object is incomplete, and failing + // if the parser fails + // second, look for separating comma, ignoring whitespace, failing if + // any other characters are encountered + if (status->expecting_comma) { + for (; buffer_pos < status->buffer_index; ++buffer_pos) { + if (status->buffer[buffer_pos] == ',') { + status->expecting_comma = false; + ++buffer_pos; + break; + } else if (!isspace(status->buffer[buffer_pos])) { + wlr_log(WLR_DEBUG, "Invalid i3bar json: expected ',' but encountered '%c'", + status->buffer[buffer_pos]); + status_error(status, "[invalid i3bar json]"); + return true; + } + } + if (buffer_pos < status->buffer_index) { + continue; // look for new object without reading more input } - state->escape = !state->escape && *cur == '\\'; + buffer_pos = status->buffer_index = 0; } else { - switch (*cur) { - case '[': - ++state->depth; - if (state->depth > - sizeof(state->nodes) / sizeof(state->nodes[0])) { - status_error(status, "[i3bar json too deep]"); - return false; - } - state->nodes[state->depth] = JSON_NODE_ARRAY; - if (state->depth == 1) { - state->current_node = cur; + test_object = json_tokener_parse_ex(status->tokener, + &status->buffer[buffer_pos], status->buffer_index - buffer_pos); + enum json_tokener_error err = json_tokener_get_error(status->tokener); + if (err == json_tokener_success) { + if (json_object_get_type(test_object) == json_type_array) { + if (last_object) { + json_object_put(last_object); + } + last_object = test_object; + } else { + json_object_put(test_object); } - break; - case ']': - if (state->nodes[state->depth] != JSON_NODE_ARRAY) { - status_error(status, "[failed to parse i3bar json]"); - return false; + + // in order to print the json for debugging purposes + // the last character is temporarily replaced with a null character + // (the last character is used in case the buffer is full) + char *last_char_pos = + &status->buffer[buffer_pos + status->tokener->char_offset - 1]; + char last_char = *last_char_pos; + while (isspace(last_char)) { + last_char = *--last_char_pos; } - --state->depth; - if (state->depth == 0) { - // cur[1] is valid since cur[0] != '\0' - char p = cur[1]; - cur[1] = '\0'; - redraw = i3bar_parse_json( - status, state->current_node) || redraw; - cur[1] = p; - memmove(state->buffer, cur, - state->buffer_size - (cur - state->buffer)); - cur = state->buffer; - state->current_node = cur + 1; + *last_char_pos = '\0'; + size_t offset = strspn(&status->buffer[buffer_pos], " \f\n\r\t\v"); + wlr_log(WLR_DEBUG, "Received i3bar json: '%s%c'", + &status->buffer[buffer_pos + offset], last_char); + *last_char_pos = last_char; + + buffer_pos += status->tokener->char_offset; + status->expecting_comma = true; + + if (buffer_pos < status->buffer_index) { + continue; // look for comma without reading more input } - break; - case '"': - ++state->depth; - if (state->depth > - sizeof(state->nodes) / sizeof(state->nodes[0])) { - status_error(status, "[i3bar json too deep]"); - return false; + buffer_pos = status->buffer_index = 0; + } else if (err == json_tokener_continue) { + json_tokener_reset(status->tokener); + if (status->buffer_index < status->buffer_size) { + // move the object to the start of the buffer + status->buffer_index -= buffer_pos; + memmove(status->buffer, &status->buffer[buffer_pos], + status->buffer_index); + buffer_pos = 0; + } else { + // expand buffer + status->buffer_size *= 2; + char *new_buffer = realloc(status->buffer, status->buffer_size); + if (new_buffer) { + status->buffer = new_buffer; + } else { + free(status->buffer); + status_error(status, "[failed to allocate buffer]"); + return true; + } } - state->nodes[state->depth] = JSON_NODE_STRING; - break; + } else { + char last_char = status->buffer[status->buffer_index - 1]; + status->buffer[status->buffer_index - 1] = '\0'; + wlr_log(WLR_DEBUG, "Failed to parse i3bar json - %s: '%s%c'", + json_tokener_error_desc(err), &status->buffer[buffer_pos], last_char); + status_error(status, "[failed to parse i3bar json]"); + return true; } } - ++cur; + + errno = 0; + ssize_t read_bytes = read(status->read_fd, &status->buffer[status->buffer_index], + status->buffer_size - status->buffer_index); + if (read_bytes > -1) { + status->buffer_index += read_bytes; + } else if (errno == EAGAIN) { + break; + } else { + status_error(status, "[error reading from status command]"); + return true; + } + } + + if (last_object) { + wlr_log(WLR_DEBUG, "Rendering last received json"); + i3bar_parse_json(status, last_object); + json_object_put(last_object); + return true; + } else { + return false; } - state->buffer_index = cur - state->buffer; - return redraw; } enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, struct i3bar_block *block, int x, int y, enum x11_button button) { wlr_log(WLR_DEBUG, "block %s clicked", block->name ? block->name : "(nil)"); - if (!block->name || !status->i3bar_state.click_events) { + if (!block->name || !status->click_events) { return HOTSPOT_PROCESS; } @@ -214,7 +274,7 @@ enum hotspot_event_handling i3bar_block_send_click(struct status_line *status, json_object_object_add(event_json, "button", json_object_new_int(button)); json_object_object_add(event_json, "x", json_object_new_int(x)); json_object_object_add(event_json, "y", json_object_new_int(y)); - if (dprintf(status->write_fd, "%s\n", + if (dprintf(status->write_fd, "%s,\n", json_object_to_json_string(event_json)) < 0) { status_error(status, "[failed to write click event]"); } diff --git a/swaybar/render.c b/swaybar/render.c index 2d848bfa..26db80cb 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -1,4 +1,5 @@ #define _POSIX_C_SOURCE 200809L +#include <assert.h> #include <limits.h> #include <stdlib.h> #include <stdint.h> @@ -120,14 +121,14 @@ static void i3bar_block_unref_callback(void *data) { } static uint32_t render_status_block(cairo_t *cairo, - struct swaybar_config *config, struct swaybar_output *output, - struct i3bar_block *block, double *x, + struct swaybar_output *output, struct i3bar_block *block, double *x, uint32_t surface_height, bool focused, bool edge) { if (!block->full_text || !*block->full_text) { return 0; } uint32_t height = surface_height * output->scale; + struct swaybar_config *config = output->bar->config; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, @@ -177,16 +178,18 @@ static uint32_t render_status_block(cairo_t *cairo, *x -= margin; } - struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); - hotspot->x = *x; - hotspot->y = 0; - hotspot->width = width; - hotspot->height = height; - hotspot->callback = block_hotspot_callback; - hotspot->destroy = i3bar_block_unref_callback; - hotspot->data = block; - block->ref_count++; - wl_list_insert(&output->hotspots, &hotspot->link); + if (output->bar->status->click_events) { + struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); + hotspot->x = *x; + hotspot->y = 0; + hotspot->width = width; + hotspot->height = height; + hotspot->callback = block_hotspot_callback; + hotspot->destroy = i3bar_block_unref_callback; + hotspot->data = block; + block->ref_count++; + wl_list_insert(&output->hotspots, &hotspot->link); + } double pos = *x; if (block->background) { @@ -268,7 +271,7 @@ static uint32_t render_status_line_i3bar(cairo_t *cairo, bool edge = true; struct i3bar_block *block; wl_list_for_each(block, &status->blocks, link) { - uint32_t h = render_status_block(cairo, config, output, + uint32_t h = render_status_block(cairo, output, block, x, surface_height, focused, edge); max_height = h > max_height ? h : max_height; edge = false; @@ -478,6 +481,8 @@ static uint32_t render_to_cairo(cairo_t *cairo, } void render_frame(struct swaybar *bar, struct swaybar_output *output) { + assert(output->surface != NULL); + struct swaybar_hotspot *hotspot, *tmp; wl_list_for_each_safe(hotspot, tmp, &output->hotspots, link) { if (hotspot->destroy) { @@ -505,7 +510,6 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { // TODO: this could infinite loop if the compositor assigns us a // different height than what we asked for wl_surface_commit(output->surface); - wl_display_roundtrip(bar->display); } else if (height > 0) { // Replay recording into shm and send it off output->current_buffer = get_next_buffer(bar->shm, @@ -531,7 +535,6 @@ void render_frame(struct swaybar *bar, struct swaybar_output *output) { wl_surface_damage(output->surface, 0, 0, output->width, output->height); wl_surface_commit(output->surface); - wl_display_roundtrip(bar->display); } cairo_surface_destroy(recorder); cairo_destroy(cairo); diff --git a/swaybar/status_line.c b/swaybar/status_line.c index 3ba990bd..48b43248 100644 --- a/swaybar/status_line.c +++ b/swaybar/status_line.c @@ -7,86 +7,106 @@ #include <unistd.h> #include <wlr/util/log.h> #include "swaybar/config.h" +#include "swaybar/event_loop.h" #include "swaybar/status_line.h" #include "readline.h" +static void status_line_close_fds(struct status_line *status) { + if (status->read_fd != -1) { + remove_event(status->read_fd); + close(status->read_fd); + status->read_fd = -1; + } + if (status->write_fd != -1) { + close(status->write_fd); + status->write_fd = -1; + } +} + void status_error(struct status_line *status, const char *text) { - close(status->read_fd); - close(status->write_fd); + status_line_close_fds(status); status->protocol = PROTOCOL_ERROR; status->text = text; } bool status_handle_readable(struct status_line *status) { - char *line; + ssize_t read_bytes = 1; switch (status->protocol) { - case PROTOCOL_ERROR: - return false; - case PROTOCOL_I3BAR: - if (i3bar_handle_readable(status) > 0) { - return true; - } - break; - case PROTOCOL_TEXT: - line = read_line_buffer(status->read, - status->text_state.buffer, status->text_state.buffer_size); - if (!line) { - status_error(status, "[error reading from status command]"); - } else { - status->text = line; - } - return true; case PROTOCOL_UNDEF: - line = read_line_buffer(status->read, - status->text_state.buffer, status->text_state.buffer_size); - if (!line) { + errno = 0; + read_bytes = getline(&status->buffer, + &status->buffer_size, status->read); + if (errno == EAGAIN) { + clearerr(status->read); + } else if (errno) { status_error(status, "[error reading from status command]"); - return false; + return true; } - if (line[0] == '{') { - json_object *proto = json_tokener_parse(line); - if (proto) { - json_object *version; - if (json_object_object_get_ex(proto, "version", &version) - && json_object_get_int(version) == 1) { - wlr_log(WLR_DEBUG, "Switched to i3bar protocol."); - status->protocol = PROTOCOL_I3BAR; - } - json_object *click_events; - if (json_object_object_get_ex( - proto, "click_events", &click_events) - && json_object_get_boolean(click_events)) { - wlr_log(WLR_DEBUG, "Enabled click events."); - status->i3bar_state.click_events = true; - const char *events_array = "[\n"; - ssize_t len = strlen(events_array); - if (write(status->write_fd, events_array, len) != len) { - status_error(status, - "[failed to write to status command]"); - } + + // the header must be sent completely the first time round + json_object *header, *version; + if (status->buffer[read_bytes - 1] == '\n' + && (header = json_tokener_parse(status->buffer)) + && json_object_object_get_ex(header, "version", &version) + && json_object_get_int(version) == 1) { + wlr_log(WLR_DEBUG, "Using i3bar protocol."); + status->protocol = PROTOCOL_I3BAR; + + json_object *click_events; + if (json_object_object_get_ex(header, "click_events", &click_events) + && json_object_get_boolean(click_events)) { + wlr_log(WLR_DEBUG, "Enabling click events."); + status->click_events = true; + if (write(status->write_fd, "[\n", 2) != 2) { + status_error(status, "[failed to write to status command]"); + json_object_put(header); + return true; } - json_object_put(proto); } + json_object_put(header); - status->protocol = PROTOCOL_I3BAR; - free(status->text_state.buffer); wl_list_init(&status->blocks); - status->i3bar_state.buffer_size = 4096; - status->i3bar_state.buffer = - malloc(status->i3bar_state.buffer_size); - } else { - status->protocol = PROTOCOL_TEXT; - status->text = line; + status->tokener = json_tokener_new(); + read_bytes = getdelim(&status->buffer, &status->buffer_size, EOF, status->read); + if (read_bytes > 0) { + status->buffer_index = read_bytes; + return i3bar_handle_readable(status); + } else { + return false; + } + } + + wlr_log(WLR_DEBUG, "Using text protocol."); + status->protocol = PROTOCOL_TEXT; + status->text = status->buffer; + // intentional fall-through + case PROTOCOL_TEXT: + errno = 0; + while (true) { + if (status->buffer[read_bytes - 1] == '\n') { + status->buffer[read_bytes - 1] = '\0'; + } + read_bytes = getline(&status->buffer, + &status->buffer_size, status->read); + if (errno == EAGAIN) { + clearerr(status->read); + return true; + } else if (errno) { + status_error(status, "[error reading from status command]"); + return true; + } } - return true; + case PROTOCOL_I3BAR: + return i3bar_handle_readable(status); + default: + return false; } - return false; } struct status_line *status_line_init(char *cmd) { struct status_line *status = calloc(1, sizeof(struct status_line)); - status->text_state.buffer_size = 8192; - status->text_state.buffer = malloc(status->text_state.buffer_size); + status->buffer_size = 8192; + status->buffer = malloc(status->buffer_size); int pipe_read_fd[2]; int pipe_write_fd[2]; @@ -123,20 +143,16 @@ struct status_line *status_line_init(char *cmd) { } void status_line_free(struct status_line *status) { - close(status->read_fd); - close(status->write_fd); + status_line_close_fds(status); kill(status->pid, SIGTERM); - switch (status->protocol) { - case PROTOCOL_I3BAR:; + if (status->protocol == PROTOCOL_I3BAR) { struct i3bar_block *block, *tmp; wl_list_for_each_safe(block, tmp, &status->blocks, link) { + wl_list_remove(&block->link); i3bar_block_unref(block); } - free(status->i3bar_state.buffer); - break; - default: - free(status->text_state.buffer); - break; + json_tokener_free(status->tokener); } + free(status->buffer); free(status); } |