diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-03-31 14:39:18 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-04-02 11:09:23 -0400 |
commit | 333dbcbe72b6af95573e374b66ad6ab63f274299 (patch) | |
tree | b73facc5f8399ca6328898749941d5ae195dec8d /swaybar/i3bar.c | |
parent | Demarcate i3bar JSON into individual updates (diff) | |
download | sway-333dbcbe72b6af95573e374b66ad6ab63f274299.tar.gz sway-333dbcbe72b6af95573e374b66ad6ab63f274299.tar.zst sway-333dbcbe72b6af95573e374b66ad6ab63f274299.zip |
Render i3bar blocks
Diffstat (limited to 'swaybar/i3bar.c')
-rw-r--r-- | swaybar/i3bar.c | 120 |
1 files changed, 110 insertions, 10 deletions
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c index 5be348b2..41b71164 100644 --- a/swaybar/i3bar.c +++ b/swaybar/i3bar.c | |||
@@ -1,3 +1,5 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <json-c/json.h> | ||
1 | #include <stdlib.h> | 3 | #include <stdlib.h> |
2 | #include <string.h> | 4 | #include <string.h> |
3 | #include <unistd.h> | 5 | #include <unistd.h> |
@@ -5,11 +7,109 @@ | |||
5 | #include "swaybar/config.h" | 7 | #include "swaybar/config.h" |
6 | #include "swaybar/status_line.h" | 8 | #include "swaybar/status_line.h" |
7 | 9 | ||
8 | static void i3bar_parse_json(struct status_line *status, const char *text) { | 10 | static void i3bar_block_free(struct i3bar_block *block) { |
9 | wlr_log(L_DEBUG, "got json: %s", text); | 11 | if (!block) { |
12 | return; | ||
13 | } | ||
14 | wl_list_remove(&block->link); | ||
15 | free(block->full_text); | ||
16 | free(block->short_text); | ||
17 | free(block->align); | ||
18 | free(block->name); | ||
19 | free(block->instance); | ||
20 | free(block->color); | ||
21 | } | ||
22 | |||
23 | static bool i3bar_parse_json(struct status_line *status, const char *text) { | ||
24 | struct i3bar_block *block, *tmp; | ||
25 | wl_list_for_each_safe(block, tmp, &status->blocks, link) { | ||
26 | i3bar_block_free(block); | ||
27 | } | ||
28 | json_object *results = json_tokener_parse(text); | ||
29 | if (!results) { | ||
30 | status_error(status, "[failed to parse i3bar json]"); | ||
31 | return false; | ||
32 | } | ||
33 | if (json_object_array_length(results) < 1) { | ||
34 | return true; | ||
35 | } | ||
36 | for (size_t i = 0; i < json_object_array_length(results); ++i) { | ||
37 | json_object *full_text, *short_text, *color, *min_width, *align, *urgent; | ||
38 | json_object *name, *instance, *separator, *separator_block_width; | ||
39 | json_object *background, *border, *border_top, *border_bottom; | ||
40 | json_object *border_left, *border_right, *markup; | ||
41 | json_object *json = json_object_array_get_idx(results, i); | ||
42 | if (!json) { | ||
43 | continue; | ||
44 | } | ||
45 | json_object_object_get_ex(json, "full_text", &full_text); | ||
46 | json_object_object_get_ex(json, "short_text", &short_text); | ||
47 | json_object_object_get_ex(json, "color", &color); | ||
48 | json_object_object_get_ex(json, "min_width", &min_width); | ||
49 | json_object_object_get_ex(json, "align", &align); | ||
50 | json_object_object_get_ex(json, "urgent", &urgent); | ||
51 | json_object_object_get_ex(json, "name", &name); | ||
52 | json_object_object_get_ex(json, "instance", &instance); | ||
53 | json_object_object_get_ex(json, "markup", &markup); | ||
54 | json_object_object_get_ex(json, "separator", &separator); | ||
55 | json_object_object_get_ex(json, "separator_block_width", &separator_block_width); | ||
56 | json_object_object_get_ex(json, "background", &background); | ||
57 | json_object_object_get_ex(json, "border", &border); | ||
58 | json_object_object_get_ex(json, "border_top", &border_top); | ||
59 | json_object_object_get_ex(json, "border_bottom", &border_bottom); | ||
60 | json_object_object_get_ex(json, "border_left", &border_left); | ||
61 | json_object_object_get_ex(json, "border_right", &border_right); | ||
62 | |||
63 | struct i3bar_block *block = calloc(1, sizeof(struct i3bar_block)); | ||
64 | block->full_text = full_text ? | ||
65 | strdup(json_object_get_string(full_text)) : NULL; | ||
66 | block->short_text = short_text ? | ||
67 | strdup(json_object_get_string(short_text)) : NULL; | ||
68 | if (color) { | ||
69 | block->color = malloc(sizeof(uint32_t)); | ||
70 | *block->color = parse_color(json_object_get_string(color)); | ||
71 | } | ||
72 | if (min_width) { | ||
73 | json_type type = json_object_get_type(min_width); | ||
74 | if (type == json_type_int) { | ||
75 | block->min_width = json_object_get_int(min_width); | ||
76 | } else if (type == json_type_string) { | ||
77 | /* the width will be calculated when rendering */ | ||
78 | block->min_width = 0; | ||
79 | } | ||
80 | } | ||
81 | block->align = strdup(align ? json_object_get_string(align) : "left"); | ||
82 | block->urgent = urgent ? json_object_get_int(urgent) : false; | ||
83 | block->name = name ? strdup(json_object_get_string(name)) : NULL; | ||
84 | block->instance = instance ? | ||
85 | strdup(json_object_get_string(instance)) : NULL; | ||
86 | if (markup) { | ||
87 | block->markup = false; | ||
88 | const char *markup_str = json_object_get_string(markup); | ||
89 | if (strcmp(markup_str, "pango") == 0) { | ||
90 | block->markup = true; | ||
91 | } | ||
92 | } | ||
93 | block->separator = separator ? json_object_get_int(separator) : true; | ||
94 | block->separator_block_width = separator_block_width ? | ||
95 | json_object_get_int(separator_block_width) : 9; | ||
96 | // Airblader features | ||
97 | block->background = background ? | ||
98 | parse_color(json_object_get_string(background)) : 0; | ||
99 | block->border = border ? | ||
100 | parse_color(json_object_get_string(border)) : 0; | ||
101 | block->border_top = border_top ? json_object_get_int(border_top) : 1; | ||
102 | block->border_bottom = border_bottom ? | ||
103 | json_object_get_int(border_bottom) : 1; | ||
104 | block->border_left = border_left ? json_object_get_int(border_left) : 1; | ||
105 | block->border_right = border_right ? | ||
106 | json_object_get_int(border_right) : 1; | ||
107 | wl_list_insert(&status->blocks, &block->link); | ||
108 | } | ||
109 | return true; | ||
10 | } | 110 | } |
11 | 111 | ||
12 | int i3bar_readable(struct status_line *status) { | 112 | bool i3bar_handle_readable(struct status_line *status) { |
13 | struct i3bar_protocol_state *state = &status->i3bar_state; | 113 | struct i3bar_protocol_state *state = &status->i3bar_state; |
14 | 114 | ||
15 | char *cur = &state->buffer[state->buffer_index]; | 115 | char *cur = &state->buffer[state->buffer_index]; |
@@ -30,7 +130,7 @@ int i3bar_readable(struct status_line *status) { | |||
30 | state->buffer = new_buffer; | 130 | state->buffer = new_buffer; |
31 | } | 131 | } |
32 | 132 | ||
33 | int handled = 0; | 133 | bool redraw = false; |
34 | while (*cur) { | 134 | while (*cur) { |
35 | if (state->nodes[state->depth] == JSON_NODE_STRING) { | 135 | if (state->nodes[state->depth] == JSON_NODE_STRING) { |
36 | if (!state->escape && *cur == '"') { | 136 | if (!state->escape && *cur == '"') { |
@@ -44,7 +144,7 @@ int i3bar_readable(struct status_line *status) { | |||
44 | if (state->depth > | 144 | if (state->depth > |
45 | sizeof(state->nodes) / sizeof(state->nodes[0])) { | 145 | sizeof(state->nodes) / sizeof(state->nodes[0])) { |
46 | status_error(status, "[i3bar json too deep]"); | 146 | status_error(status, "[i3bar json too deep]"); |
47 | return -1; | 147 | return false; |
48 | } | 148 | } |
49 | state->nodes[state->depth] = JSON_NODE_ARRAY; | 149 | state->nodes[state->depth] = JSON_NODE_ARRAY; |
50 | if (state->depth == 1) { | 150 | if (state->depth == 1) { |
@@ -54,18 +154,18 @@ int i3bar_readable(struct status_line *status) { | |||
54 | case ']': | 154 | case ']': |
55 | if (state->nodes[state->depth] != JSON_NODE_ARRAY) { | 155 | if (state->nodes[state->depth] != JSON_NODE_ARRAY) { |
56 | status_error(status, "[failed to parse i3bar json]"); | 156 | status_error(status, "[failed to parse i3bar json]"); |
57 | return -1; | 157 | return false; |
58 | } | 158 | } |
59 | --state->depth; | 159 | --state->depth; |
60 | if (state->depth == 0) { | 160 | if (state->depth == 0) { |
61 | // cur[1] is valid since cur[0] != '\0' | 161 | // cur[1] is valid since cur[0] != '\0' |
62 | char p = cur[1]; | 162 | char p = cur[1]; |
63 | cur[1] = '\0'; | 163 | cur[1] = '\0'; |
64 | i3bar_parse_json(status, state->current_node); | 164 | redraw = i3bar_parse_json( |
165 | status, state->current_node) || redraw; | ||
65 | cur[1] = p; | 166 | cur[1] = p; |
66 | memmove(state->buffer, cur, | 167 | memmove(state->buffer, cur, |
67 | state->buffer_size - (cur - state->buffer)); | 168 | state->buffer_size - (cur - state->buffer)); |
68 | ++handled; | ||
69 | cur = state->buffer; | 169 | cur = state->buffer; |
70 | state->current_node = cur + 1; | 170 | state->current_node = cur + 1; |
71 | } | 171 | } |
@@ -75,7 +175,7 @@ int i3bar_readable(struct status_line *status) { | |||
75 | if (state->depth > | 175 | if (state->depth > |
76 | sizeof(state->nodes) / sizeof(state->nodes[0])) { | 176 | sizeof(state->nodes) / sizeof(state->nodes[0])) { |
77 | status_error(status, "[i3bar json too deep]"); | 177 | status_error(status, "[i3bar json too deep]"); |
78 | return -1; | 178 | return false; |
79 | } | 179 | } |
80 | state->nodes[state->depth] = JSON_NODE_STRING; | 180 | state->nodes[state->depth] = JSON_NODE_STRING; |
81 | break; | 181 | break; |
@@ -84,5 +184,5 @@ int i3bar_readable(struct status_line *status) { | |||
84 | ++cur; | 184 | ++cur; |
85 | } | 185 | } |
86 | state->buffer_index = cur - state->buffer; | 186 | state->buffer_index = cur - state->buffer; |
87 | return handled; | 187 | return redraw; |
88 | } | 188 | } |