aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-03-31 13:07:22 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2018-04-02 11:09:23 -0400
commitee85c918317ec6a685a999db46f692c7d13cdf2a (patch)
tree34afb98bc7fccb8ea6d215c710579e62a459cb62 /swaybar
parentMerge pull request #1684 from swaywm/follow-warp (diff)
downloadsway-ee85c918317ec6a685a999db46f692c7d13cdf2a.tar.gz
sway-ee85c918317ec6a685a999db46f692c7d13cdf2a.tar.zst
sway-ee85c918317ec6a685a999db46f692c7d13cdf2a.zip
Demarcate i3bar JSON into individual updates
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/i3bar.c88
-rw-r--r--swaybar/meson.build1
-rw-r--r--swaybar/status_line.c62
3 files changed, 142 insertions, 9 deletions
diff --git a/swaybar/i3bar.c b/swaybar/i3bar.c
new file mode 100644
index 00000000..5be348b2
--- /dev/null
+++ b/swaybar/i3bar.c
@@ -0,0 +1,88 @@
1#include <stdlib.h>
2#include <string.h>
3#include <unistd.h>
4#include <wlr/util/log.h>
5#include "swaybar/config.h"
6#include "swaybar/status_line.h"
7
8static void i3bar_parse_json(struct status_line *status, const char *text) {
9 wlr_log(L_DEBUG, "got json: %s", text);
10}
11
12int i3bar_readable(struct status_line *status) {
13 struct i3bar_protocol_state *state = &status->i3bar_state;
14
15 char *cur = &state->buffer[state->buffer_index];
16 ssize_t n = read(status->read_fd, cur,
17 state->buffer_size - state->buffer_index);
18 if (n == 0) {
19 return 0;
20 }
21
22 if (n == (ssize_t)(state->buffer_size - state->buffer_index)) {
23 state->buffer_size = state->buffer_size * 2;
24 char *new_buffer = realloc(state->buffer, state->buffer_size);
25 if (!new_buffer) {
26 free(state->buffer);
27 status_error(status, "[failed to allocate buffer]");
28 return -1;
29 }
30 state->buffer = new_buffer;
31 }
32
33 int handled = 0;
34 while (*cur) {
35 if (state->nodes[state->depth] == JSON_NODE_STRING) {
36 if (!state->escape && *cur == '"') {
37 --state->depth;
38 }
39 state->escape = !state->escape && *cur == '\\';
40 } else {
41 switch (*cur) {
42 case '[':
43 ++state->depth;
44 if (state->depth >
45 sizeof(state->nodes) / sizeof(state->nodes[0])) {
46 status_error(status, "[i3bar json too deep]");
47 return -1;
48 }
49 state->nodes[state->depth] = JSON_NODE_ARRAY;
50 if (state->depth == 1) {
51 state->current_node = cur;
52 }
53 break;
54 case ']':
55 if (state->nodes[state->depth] != JSON_NODE_ARRAY) {
56 status_error(status, "[failed to parse i3bar json]");
57 return -1;
58 }
59 --state->depth;
60 if (state->depth == 0) {
61 // cur[1] is valid since cur[0] != '\0'
62 char p = cur[1];
63 cur[1] = '\0';
64 i3bar_parse_json(status, state->current_node);
65 cur[1] = p;
66 memmove(state->buffer, cur,
67 state->buffer_size - (cur - state->buffer));
68 ++handled;
69 cur = state->buffer;
70 state->current_node = cur + 1;
71 }
72 break;
73 case '"':
74 ++state->depth;
75 if (state->depth >
76 sizeof(state->nodes) / sizeof(state->nodes[0])) {
77 status_error(status, "[i3bar json too deep]");
78 return -1;
79 }
80 state->nodes[state->depth] = JSON_NODE_STRING;
81 break;
82 }
83 }
84 ++cur;
85 }
86 state->buffer_index = cur - state->buffer;
87 return handled;
88}
diff --git a/swaybar/meson.build b/swaybar/meson.build
index bf6f6d7a..d65edb11 100644
--- a/swaybar/meson.build
+++ b/swaybar/meson.build
@@ -3,6 +3,7 @@ executable(
3 'bar.c', 3 'bar.c',
4 'config.c', 4 'config.c',
5 'event_loop.c', 5 'event_loop.c',
6 'i3bar.c',
6 'ipc.c', 7 'ipc.c',
7 'main.c', 8 'main.c',
8 'render.c', 9 'render.c',
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
index 3454f207..c94ac6d4 100644
--- a/swaybar/status_line.c
+++ b/swaybar/status_line.c
@@ -1,5 +1,6 @@
1#define _POSIX_C_SOURCE 1#define _POSIX_C_SOURCE
2#include <fcntl.h> 2#include <fcntl.h>
3#include <json-c/json.h>
3#include <stdlib.h> 4#include <stdlib.h>
4#include <string.h> 5#include <string.h>
5#include <stdio.h> 6#include <stdio.h>
@@ -9,35 +10,78 @@
9#include "swaybar/status_line.h" 10#include "swaybar/status_line.h"
10#include "readline.h" 11#include "readline.h"
11 12
13void status_error(struct status_line *status, const char *text) {
14 close(status->read_fd);
15 close(status->write_fd);
16 status->protocol = PROTOCOL_ERROR;
17 status->text = text;
18}
19
12bool handle_status_readable(struct status_line *status) { 20bool handle_status_readable(struct status_line *status) {
13 char *line = read_line_buffer(status->read, 21 char *line;
14 status->buffer, status->buffer_size);
15 switch (status->protocol) { 22 switch (status->protocol) {
23 case PROTOCOL_ERROR:
24 return false;
16 case PROTOCOL_I3BAR: 25 case PROTOCOL_I3BAR:
17 // TODO 26 if (i3bar_readable(status) > 0) {
27 return true;
28 }
18 break; 29 break;
19 case PROTOCOL_TEXT: 30 case PROTOCOL_TEXT:
20 status->text = line; 31 line = read_line_buffer(status->read,
32 status->text_state.buffer, status->text_state.buffer_size);
33 if (!line) {
34 status_error(status, "[error reading from status command]");
35 } else {
36 status->text = line;
37 }
21 return true; 38 return true;
22 case PROTOCOL_UNDEF: 39 case PROTOCOL_UNDEF:
40 line = read_line_buffer(status->read,
41 status->text_state.buffer, status->text_state.buffer_size);
23 if (!line) { 42 if (!line) {
43 status_error(status, "[error reading from status command]");
24 return false; 44 return false;
25 } 45 }
26 if (line[0] == '{') { 46 if (line[0] == '{') {
27 // TODO: JSON 47 json_object *proto = json_tokener_parse(line);
48 if (proto) {
49 json_object *version;
50 if (json_object_object_get_ex(proto, "version", &version)
51 && json_object_get_int(version) == 1) {
52 wlr_log(L_DEBUG, "Switched to i3bar protocol.");
53 status->protocol = PROTOCOL_I3BAR;
54 }
55 json_object *click_events;
56 if (json_object_object_get_ex(
57 proto, "click_events", &click_events)
58 && json_object_get_boolean(click_events)) {
59 wlr_log(L_DEBUG, "Enabled click events.");
60 status->i3bar_state.click_events = true;
61 const char *events_array = "[\n";
62 write(status->write_fd, events_array, strlen(events_array));
63 }
64 json_object_put(proto);
65 }
66
67 status->protocol = PROTOCOL_I3BAR;
68 free(status->text_state.buffer);
69 status->i3bar_state.buffer_size = 4096;
70 status->i3bar_state.buffer =
71 malloc(status->i3bar_state.buffer_size);
28 } else { 72 } else {
29 status->text = line;
30 status->protocol = PROTOCOL_TEXT; 73 status->protocol = PROTOCOL_TEXT;
74 status->text = line;
31 } 75 }
32 return false; 76 return true;
33 } 77 }
34 return false; 78 return false;
35} 79}
36 80
37struct status_line *status_line_init(char *cmd) { 81struct status_line *status_line_init(char *cmd) {
38 struct status_line *status = calloc(1, sizeof(struct status_line)); 82 struct status_line *status = calloc(1, sizeof(struct status_line));
39 status->buffer_size = 4096; 83 status->text_state.buffer_size = 8192;
40 status->buffer = malloc(status->buffer_size); 84 status->text_state.buffer = malloc(status->text_state.buffer_size);
41 85
42 int pipe_read_fd[2]; 86 int pipe_read_fd[2];
43 int pipe_write_fd[2]; 87 int pipe_write_fd[2];