summaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-01-24 02:34:20 +0100
committerLibravatar Mikkel Oscar Lyderik <mikkeloscar@gmail.com>2016-01-24 14:22:19 +0100
commitaa6ad09183d623647bc8fd5315721bd8b196cafa (patch)
treebeab8b4222dd5a5a97394a9da0b8704f1b6e5df8 /swaybar
parentswaybar: move core functionality to state.c (diff)
downloadsway-aa6ad09183d623647bc8fd5315721bd8b196cafa.tar.gz
sway-aa6ad09183d623647bc8fd5315721bd8b196cafa.tar.zst
sway-aa6ad09183d623647bc8fd5315721bd8b196cafa.zip
swaybar: rename state to bar
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/CMakeLists.txt2
-rw-r--r--swaybar/bar.c185
-rw-r--r--swaybar/bar.h (renamed from swaybar/state.h)22
-rw-r--r--swaybar/config.c6
-rw-r--r--swaybar/config.h6
-rw-r--r--swaybar/ipc.c46
-rw-r--r--swaybar/ipc.h6
-rw-r--r--swaybar/main.c15
-rw-r--r--swaybar/render.c8
-rw-r--r--swaybar/render.h4
-rw-r--r--swaybar/state.c185
-rw-r--r--swaybar/status_line.c58
-rw-r--r--swaybar/status_line.h4
13 files changed, 274 insertions, 273 deletions
diff --git a/swaybar/CMakeLists.txt b/swaybar/CMakeLists.txt
index 474d8474..7f3cb383 100644
--- a/swaybar/CMakeLists.txt
+++ b/swaybar/CMakeLists.txt
@@ -10,7 +10,7 @@ add_executable(swaybar
10 main.c 10 main.c
11 config.c 11 config.c
12 render.c 12 render.c
13 state.c 13 bar.c
14 status_line.c 14 status_line.c
15 ipc.c 15 ipc.c
16) 16)
diff --git a/swaybar/bar.c b/swaybar/bar.c
new file mode 100644
index 00000000..fc01863b
--- /dev/null
+++ b/swaybar/bar.c
@@ -0,0 +1,185 @@
1#include <stdlib.h>
2#include <unistd.h>
3#include <fcntl.h>
4#include <errno.h>
5#include <sys/types.h>
6#include <sys/wait.h>
7
8#include "ipc-client.h"
9#include "list.h"
10#include "log.h"
11#include "ipc.h"
12#include "render.h"
13#include "config.h"
14#include "status_line.h"
15#include "bar.h"
16
17static void bar_init(struct bar *bar) {
18 bar->config = init_config();
19 bar->status = init_status_line();
20 bar->output = malloc(sizeof(struct output));
21 bar->output->window = NULL;
22 bar->output->registry = NULL;
23 bar->output->workspaces = create_list();
24 bar->output->name = NULL;
25}
26
27static void spawn_status_cmd_proc(struct bar *bar) {
28 if (bar->config->status_command) {
29 int pipefd[2];
30 pipe(pipefd);
31 bar->status_command_pid = fork();
32 if (bar->status_command_pid == 0) {
33 close(pipefd[0]);
34 dup2(pipefd[1], STDOUT_FILENO);
35 close(pipefd[1]);
36 char *const cmd[] = {
37 "sh",
38 "-c",
39 bar->config->status_command,
40 NULL,
41 };
42 execvp(cmd[0], cmd);
43 return;
44 }
45
46 close(pipefd[1]);
47 bar->status_read_fd = pipefd[0];
48 fcntl(bar->status_read_fd, F_SETFL, O_NONBLOCK);
49 }
50}
51
52
53void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id, int desired_output) {
54 /* initialize bar with default values */
55 bar_init(bar);
56
57 bar->output->registry = registry_poll();
58
59 if (!bar->output->registry->desktop_shell) {
60 sway_abort("swaybar requires the compositor to support the desktop-shell extension.");
61 }
62
63 /* connect to sway ipc */
64 bar->ipc_socketfd = ipc_open_socket(socket_path);
65 bar->ipc_event_socketfd = ipc_open_socket(socket_path);
66
67 ipc_bar_init(bar, desired_output, bar_id);
68
69 struct output_state *output = bar->output->registry->outputs->items[desired_output];
70
71 bar->output->window = window_setup(bar->output->registry, output->width, 30, false);
72 if (!bar->output->window) {
73 sway_abort("Failed to create window.");
74 }
75 desktop_shell_set_panel(bar->output->registry->desktop_shell, output->output, bar->output->window->surface);
76 desktop_shell_set_panel_position(bar->output->registry->desktop_shell, bar->config->position);
77
78 /* set font */
79 bar->output->window->font = bar->config->font;
80
81 /* set window height */
82 set_window_height(bar->output->window, bar->config->height);
83
84 /* spawn status command */
85 spawn_status_cmd_proc(bar);
86}
87
88void bar_run(struct bar *bar) {
89 fd_set readfds;
90 int activity;
91 bool dirty = true;
92
93 while (1) {
94 if (dirty) {
95 struct output *output = bar->output;
96 if (window_prerender(output->window) && output->window->cairo) {
97 render(output, bar->config, bar->status);
98 window_render(output->window);
99 if (wl_display_dispatch(output->registry->display) == -1) {
100 break;
101 }
102 }
103 }
104
105 dirty = false;
106 FD_ZERO(&readfds);
107 FD_SET(bar->ipc_event_socketfd, &readfds);
108 FD_SET(bar->status_read_fd, &readfds);
109
110 activity = select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
111 if (activity < 0) {
112 sway_log(L_ERROR, "polling failed: %d", errno);
113 }
114
115 if (FD_ISSET(bar->ipc_event_socketfd, &readfds)) {
116 sway_log(L_DEBUG, "Got IPC event.");
117 dirty = handle_ipc_event(bar);
118 }
119
120 if (bar->config->status_command && FD_ISSET(bar->status_read_fd, &readfds)) {
121 sway_log(L_DEBUG, "Got update from status command.");
122 dirty = handle_status_line(bar);
123 }
124 }
125}
126
127void free_workspaces(list_t *workspaces) {
128 int i;
129 for (i = 0; i < workspaces->length; ++i) {
130 struct workspace *ws = workspaces->items[i];
131 free(ws->name);
132 free(ws);
133 }
134 list_free(workspaces);
135}
136
137static void free_output(struct output *output) {
138 window_teardown(output->window);
139 if (output->registry) {
140 registry_teardown(output->registry);
141 }
142
143 free(output->name);
144
145 if (output->workspaces) {
146 free_workspaces(output->workspaces);
147 }
148
149 free(output);
150}
151
152static void terminate_status_command(pid_t pid) {
153 if (pid) {
154 // terminate status_command process
155 int ret = kill(pid, SIGTERM);
156 if (ret != 0) {
157 sway_log(L_ERROR, "Unable to terminate status_command [pid: %d]", pid);
158 } else {
159 int status;
160 waitpid(pid, &status, 0);
161 }
162 }
163}
164
165void bar_teardown(struct bar *bar) {
166 free_config(bar->config);
167 free_output(bar->output);
168 free_status_line(bar->status);
169
170 /* close sockets/pipes */
171 if (bar->status_read_fd) {
172 close(bar->status_read_fd);
173 }
174
175 if (bar->ipc_socketfd) {
176 close(bar->ipc_socketfd);
177 }
178
179 if (bar->ipc_event_socketfd) {
180 close(bar->ipc_event_socketfd);
181 }
182
183 /* terminate status command process */
184 terminate_status_command(bar->status_command_pid);
185}
diff --git a/swaybar/state.h b/swaybar/bar.h
index 985002f8..89496da6 100644
--- a/swaybar/state.h
+++ b/swaybar/bar.h
@@ -1,12 +1,12 @@
1#ifndef _SWAYBAR_STATE_H 1#ifndef _SWAYBAR_BAR_H
2#define _SWAYBAR_STATE_H 2#define _SWAYBAR_BAR_H
3 3
4#include "client/registry.h" 4#include "client/registry.h"
5#include "client/window.h" 5#include "client/window.h"
6#include "list.h" 6#include "list.h"
7 7
8struct swaybar_state { 8struct bar {
9 struct swaybar_config *config; 9 struct config *config;
10 struct status_line *status; 10 struct status_line *status;
11 struct output *output; 11 struct output *output;
12 /* list_t *outputs; */ 12 /* list_t *outputs; */
@@ -33,14 +33,14 @@ struct workspace {
33}; 33};
34 34
35/** 35/**
36 * Setup state. 36 * Setup bar.
37 */ 37 */
38void state_setup(struct swaybar_state *state, const char *socket_path, const char *bar_id, int desired_output); 38void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id, int desired_output);
39 39
40/** 40/**
41 * State mainloop. 41 * Bar mainloop.
42 */ 42 */
43void state_run(struct swaybar_state *state); 43void bar_run(struct bar *bar);
44 44
45/** 45/**
46 * free workspace list. 46 * free workspace list.
@@ -48,8 +48,8 @@ void state_run(struct swaybar_state *state);
48void free_workspaces(list_t *workspaces); 48void free_workspaces(list_t *workspaces);
49 49
50/** 50/**
51 * Teardown state. 51 * Teardown bar.
52 */ 52 */
53void state_teardown(struct swaybar_state *state); 53void bar_teardown(struct bar *bar);
54 54
55#endif /* _SWAYBAR_STATE_H */ 55#endif /* _SWAYBAR_BAR_H */
diff --git a/swaybar/config.c b/swaybar/config.c
index 7c03198a..28b609e6 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -41,8 +41,8 @@ char *parse_font(const char *font) {
41 return new_font; 41 return new_font;
42} 42}
43 43
44struct swaybar_config *init_config() { 44struct config *init_config() {
45 struct swaybar_config *config = calloc(1, sizeof(struct swaybar_config)); 45 struct config *config = calloc(1, sizeof(struct config));
46 config->status_command = NULL; 46 config->status_command = NULL;
47 config->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM; 47 config->position = DESKTOP_SHELL_PANEL_POSITION_BOTTOM;
48 config->font = strdup("monospace 10"); 48 config->font = strdup("monospace 10");
@@ -83,7 +83,7 @@ struct swaybar_config *init_config() {
83 return config; 83 return config;
84} 84}
85 85
86void free_config(struct swaybar_config *config) { 86void free_config(struct config *config) {
87 free(config->status_command); 87 free(config->status_command);
88 free(config->font); 88 free(config->font);
89 free(config->mode); 89 free(config->mode);
diff --git a/swaybar/config.h b/swaybar/config.h
index ee06668e..508b9c42 100644
--- a/swaybar/config.h
+++ b/swaybar/config.h
@@ -16,7 +16,7 @@ struct box_colors {
16/** 16/**
17 * Swaybar config. 17 * Swaybar config.
18 */ 18 */
19struct swaybar_config { 19struct config {
20 char *status_command; 20 char *status_command;
21 uint32_t position; 21 uint32_t position;
22 char *font; 22 char *font;
@@ -59,11 +59,11 @@ char *parse_font(const char *font);
59/** 59/**
60 * Initialize default sway config. 60 * Initialize default sway config.
61 */ 61 */
62struct swaybar_config *init_config(); 62struct config *init_config();
63 63
64/** 64/**
65 * Free config struct. 65 * Free config struct.
66 */ 66 */
67void free_config(struct swaybar_config *config); 67void free_config(struct config *config);
68 68
69#endif /* _SWAYBAR_CONFIG_H */ 69#endif /* _SWAYBAR_CONFIG_H */
diff --git a/swaybar/ipc.c b/swaybar/ipc.c
index 884d02ff..547041ce 100644
--- a/swaybar/ipc.c
+++ b/swaybar/ipc.c
@@ -7,14 +7,14 @@
7#include "config.h" 7#include "config.h"
8#include "ipc.h" 8#include "ipc.h"
9 9
10static void ipc_parse_config(struct swaybar_config *config, const char *payload) { 10static void ipc_parse_config(struct config *config, const char *payload) {
11 json_object *bar_config = json_tokener_parse(payload); 11 json_object *bar_config = json_tokener_parse(payload);
12 json_object *tray_output, *mode, *hidden_state, *position, *status_command; 12 json_object *tray_output, *mode, *hidden_bar, *position, *status_command;
13 json_object *font, *bar_height, *workspace_buttons, *strip_workspace_numbers; 13 json_object *font, *bar_height, *workspace_buttons, *strip_workspace_numbers;
14 json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol; 14 json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol;
15 json_object_object_get_ex(bar_config, "tray_output", &tray_output); 15 json_object_object_get_ex(bar_config, "tray_output", &tray_output);
16 json_object_object_get_ex(bar_config, "mode", &mode); 16 json_object_object_get_ex(bar_config, "mode", &mode);
17 json_object_object_get_ex(bar_config, "hidden_state", &hidden_state); 17 json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar);
18 json_object_object_get_ex(bar_config, "position", &position); 18 json_object_object_get_ex(bar_config, "position", &position);
19 json_object_object_get_ex(bar_config, "status_command", &status_command); 19 json_object_object_get_ex(bar_config, "status_command", &status_command);
20 json_object_object_get_ex(bar_config, "font", &font); 20 json_object_object_get_ex(bar_config, "font", &font);
@@ -150,14 +150,14 @@ static void ipc_parse_config(struct swaybar_config *config, const char *payload)
150 json_object_put(bar_config); 150 json_object_put(bar_config);
151} 151}
152 152
153static void ipc_update_workspaces(struct swaybar_state *state) { 153static void ipc_update_workspaces(struct bar *bar) {
154 if (state->output->workspaces) { 154 if (bar->output->workspaces) {
155 free_workspaces(state->output->workspaces); 155 free_workspaces(bar->output->workspaces);
156 } 156 }
157 state->output->workspaces = create_list(); 157 bar->output->workspaces = create_list();
158 158
159 uint32_t len = 0; 159 uint32_t len = 0;
160 char *res = ipc_single_command(state->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len); 160 char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len);
161 json_object *results = json_tokener_parse(res); 161 json_object *results = json_tokener_parse(res);
162 if (!results) { 162 if (!results) {
163 free(res); 163 free(res);
@@ -178,14 +178,14 @@ static void ipc_update_workspaces(struct swaybar_state *state) {
178 json_object_object_get_ex(ws_json, "output", &out); 178 json_object_object_get_ex(ws_json, "output", &out);
179 json_object_object_get_ex(ws_json, "urgent", &urgent); 179 json_object_object_get_ex(ws_json, "urgent", &urgent);
180 180
181 if (strcmp(json_object_get_string(out), state->output->name) == 0) { 181 if (strcmp(json_object_get_string(out), bar->output->name) == 0) {
182 struct workspace *ws = malloc(sizeof(struct workspace)); 182 struct workspace *ws = malloc(sizeof(struct workspace));
183 ws->num = json_object_get_int(num); 183 ws->num = json_object_get_int(num);
184 ws->name = strdup(json_object_get_string(name)); 184 ws->name = strdup(json_object_get_string(name));
185 ws->visible = json_object_get_boolean(visible); 185 ws->visible = json_object_get_boolean(visible);
186 ws->focused = json_object_get_boolean(focused); 186 ws->focused = json_object_get_boolean(focused);
187 ws->urgent = json_object_get_boolean(urgent); 187 ws->urgent = json_object_get_boolean(urgent);
188 list_add(state->output->workspaces, ws); 188 list_add(bar->output->workspaces, ws);
189 } 189 }
190 } 190 }
191 191
@@ -193,36 +193,36 @@ static void ipc_update_workspaces(struct swaybar_state *state) {
193 free(res); 193 free(res);
194} 194}
195 195
196void ipc_bar_init(struct swaybar_state *state, int outputi, const char *bar_id) { 196void ipc_bar_init(struct bar *bar, int outputi, const char *bar_id) {
197 uint32_t len = 0; 197 uint32_t len = 0;
198 char *res = ipc_single_command(state->ipc_socketfd, IPC_GET_OUTPUTS, NULL, &len); 198 char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_OUTPUTS, NULL, &len);
199 json_object *outputs = json_tokener_parse(res); 199 json_object *outputs = json_tokener_parse(res);
200 json_object *info = json_object_array_get_idx(outputs, outputi); 200 json_object *info = json_object_array_get_idx(outputs, outputi);
201 json_object *name; 201 json_object *name;
202 json_object_object_get_ex(info, "name", &name); 202 json_object_object_get_ex(info, "name", &name);
203 state->output->name = strdup(json_object_get_string(name)); 203 bar->output->name = strdup(json_object_get_string(name));
204 free(res); 204 free(res);
205 json_object_put(outputs); 205 json_object_put(outputs);
206 206
207 len = strlen(bar_id); 207 len = strlen(bar_id);
208 res = ipc_single_command(state->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len); 208 res = ipc_single_command(bar->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len);
209 209
210 ipc_parse_config(state->config, res); 210 ipc_parse_config(bar->config, res);
211 free(res); 211 free(res);
212 212
213 const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; 213 const char *subscribe_json = "[ \"workspace\", \"mode\" ]";
214 len = strlen(subscribe_json); 214 len = strlen(subscribe_json);
215 res = ipc_single_command(state->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len); 215 res = ipc_single_command(bar->ipc_event_socketfd, IPC_SUBSCRIBE, subscribe_json, &len);
216 free(res); 216 free(res);
217 217
218 ipc_update_workspaces(state); 218 ipc_update_workspaces(bar);
219} 219}
220 220
221bool handle_ipc_event(struct swaybar_state *state) { 221bool handle_ipc_event(struct bar *bar) {
222 struct ipc_response *resp = ipc_recv_response(state->ipc_event_socketfd); 222 struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd);
223 switch (resp->type) { 223 switch (resp->type) {
224 case IPC_EVENT_WORKSPACE: 224 case IPC_EVENT_WORKSPACE:
225 ipc_update_workspaces(state); 225 ipc_update_workspaces(bar);
226 break; 226 break;
227 case IPC_EVENT_MODE: { 227 case IPC_EVENT_MODE: {
228 json_object *result = json_tokener_parse(resp->payload); 228 json_object *result = json_tokener_parse(resp->payload);
@@ -235,11 +235,11 @@ bool handle_ipc_event(struct swaybar_state *state) {
235 if (json_object_object_get_ex(result, "change", &json_change)) { 235 if (json_object_object_get_ex(result, "change", &json_change)) {
236 const char *change = json_object_get_string(json_change); 236 const char *change = json_object_get_string(json_change);
237 237
238 free(state->config->mode); 238 free(bar->config->mode);
239 if (strcmp(change, "default") == 0) { 239 if (strcmp(change, "default") == 0) {
240 state->config->mode = NULL; 240 bar->config->mode = NULL;
241 } else { 241 } else {
242 state->config->mode = strdup(change); 242 bar->config->mode = strdup(change);
243 } 243 }
244 } else { 244 } else {
245 sway_log(L_ERROR, "failed to parse response"); 245 sway_log(L_ERROR, "failed to parse response");
diff --git a/swaybar/ipc.h b/swaybar/ipc.h
index 06d30076..c3f661f8 100644
--- a/swaybar/ipc.h
+++ b/swaybar/ipc.h
@@ -1,17 +1,17 @@
1#ifndef _SWAYBAR_IPC_H 1#ifndef _SWAYBAR_IPC_H
2#define _SWAYBAR_IPC_H 2#define _SWAYBAR_IPC_H
3 3
4#include "state.h" 4#include "bar.h"
5 5
6/** 6/**
7 * Initialize ipc connection to sway and get sway state, outputs, bar_config. 7 * Initialize ipc connection to sway and get sway state, outputs, bar_config.
8 */ 8 */
9void ipc_bar_init(struct swaybar_state *state, int outputi, const char *bar_id); 9void ipc_bar_init(struct bar *bar, int outputi, const char *bar_id);
10 10
11/** 11/**
12 * Handle ipc event from sway. 12 * Handle ipc event from sway.
13 */ 13 */
14bool handle_ipc_event(struct swaybar_state *state); 14bool handle_ipc_event(struct bar *bar);
15 15
16#endif /* _SWAYBAR_IPC_H */ 16#endif /* _SWAYBAR_IPC_H */
17 17
diff --git a/swaybar/main.c b/swaybar/main.c
index 51846bca..fc5acdae 100644
--- a/swaybar/main.c
+++ b/swaybar/main.c
@@ -5,17 +5,18 @@
5#include <getopt.h> 5#include <getopt.h>
6#include "ipc-client.h" 6#include "ipc-client.h"
7#include "log.h" 7#include "log.h"
8#include "state.h" 8#include "bar.h"
9 9
10struct swaybar_state state; 10/* global bar state */
11struct bar swaybar;
11 12
12void sway_terminate(void) { 13void sway_terminate(void) {
13 state_teardown(&state); 14 bar_teardown(&swaybar);
14 exit(EXIT_FAILURE); 15 exit(EXIT_FAILURE);
15} 16}
16 17
17void sig_handler(int signal) { 18void sig_handler(int signal) {
18 state_teardown(&state); 19 bar_teardown(&swaybar);
19 exit(0); 20 exit(0);
20} 21}
21 22
@@ -102,15 +103,15 @@ int main(int argc, char **argv) {
102 103
103 signal(SIGTERM, sig_handler); 104 signal(SIGTERM, sig_handler);
104 105
105 state_setup(&state, socket_path, bar_id, desired_output); 106 bar_setup(&swaybar, socket_path, bar_id, desired_output);
106 107
107 free(socket_path); 108 free(socket_path);
108 free(bar_id); 109 free(bar_id);
109 110
110 state_run(&state); 111 bar_run(&swaybar);
111 112
112 // gracefully shutdown swaybar and status_command 113 // gracefully shutdown swaybar and status_command
113 state_teardown(&state); 114 bar_teardown(&swaybar);
114 115
115 return 0; 116 return 0;
116} 117}
diff --git a/swaybar/render.c b/swaybar/render.c
index 9ac0c766..f3ce6010 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -55,7 +55,7 @@ static void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y
55 } 55 }
56} 56}
57 57
58static void render_block(struct window *window, struct swaybar_config *config, struct status_block *block, double *x, bool edge) { 58static void render_block(struct window *window, struct config *config, struct status_block *block, double *x, bool edge) {
59 int width, height, sep_width; 59 int width, height, sep_width;
60 get_text_size(window, &width, &height, "%s", block->full_text); 60 get_text_size(window, &width, &height, "%s", block->full_text);
61 61
@@ -203,7 +203,7 @@ static char *handle_workspace_number(bool strip_num, const char *ws_name) {
203 return strdup(ws_name); 203 return strdup(ws_name);
204} 204}
205 205
206static void render_workspace_button(struct window *window, struct swaybar_config *config, struct workspace *ws, double *x) { 206static void render_workspace_button(struct window *window, struct config *config, struct workspace *ws, double *x) {
207 // strip workspace numbers if required 207 // strip workspace numbers if required
208 char *name = handle_workspace_number(config->strip_workspace_numbers, ws->name); 208 char *name = handle_workspace_number(config->strip_workspace_numbers, ws->name);
209 209
@@ -242,7 +242,7 @@ static void render_workspace_button(struct window *window, struct swaybar_config
242 free(name); 242 free(name);
243} 243}
244 244
245static void render_binding_mode_indicator(struct window *window, struct swaybar_config *config, double pos) { 245static void render_binding_mode_indicator(struct window *window, struct config *config, double pos) {
246 int width, height; 246 int width, height;
247 get_text_size(window, &width, &height, "%s", config->mode); 247 get_text_size(window, &width, &height, "%s", config->mode);
248 248
@@ -264,7 +264,7 @@ static void render_binding_mode_indicator(struct window *window, struct swaybar_
264 pango_printf(window, "%s", config->mode); 264 pango_printf(window, "%s", config->mode);
265} 265}
266 266
267void render(struct output *output, struct swaybar_config *config, struct status_line *line) { 267void render(struct output *output, struct config *config, struct status_line *line) {
268 int i; 268 int i;
269 269
270 struct window *window = output->window; 270 struct window *window = output->window;
diff --git a/swaybar/render.h b/swaybar/render.h
index 527cf76a..931a1cdd 100644
--- a/swaybar/render.h
+++ b/swaybar/render.h
@@ -2,12 +2,12 @@
2#define _SWAYBAR_RENDER_H 2#define _SWAYBAR_RENDER_H
3 3
4#include "config.h" 4#include "config.h"
5#include "state.h" 5#include "bar.h"
6 6
7/** 7/**
8 * Render swaybar. 8 * Render swaybar.
9 */ 9 */
10void render(struct output *output, struct swaybar_config *config, struct status_line *line); 10void render(struct output *output, struct config *config, struct status_line *line);
11 11
12/** 12/**
13 * Set window height and modify internal spacing accordingly. 13 * Set window height and modify internal spacing accordingly.
diff --git a/swaybar/state.c b/swaybar/state.c
deleted file mode 100644
index 535efbc4..00000000
--- a/swaybar/state.c
+++ /dev/null
@@ -1,185 +0,0 @@
1#include <stdlib.h>
2#include <unistd.h>
3#include <fcntl.h>
4#include <errno.h>
5#include <sys/types.h>
6#include <sys/wait.h>
7
8#include "ipc-client.h"
9#include "list.h"
10#include "log.h"
11#include "ipc.h"
12#include "render.h"
13#include "config.h"
14#include "status_line.h"
15#include "state.h"
16
17static void state_init(struct swaybar_state *state) {
18 state->config = init_config();
19 state->status = init_status_line();
20 state->output = malloc(sizeof(struct output));
21 state->output->window = NULL;
22 state->output->registry = NULL;
23 state->output->workspaces = create_list();
24 state->output->name = NULL;
25}
26
27static void spawn_status_cmd_proc(struct swaybar_state *state) {
28 if (state->config->status_command) {
29 int pipefd[2];
30 pipe(pipefd);
31 state->status_command_pid = fork();
32 if (state->status_command_pid == 0) {
33 close(pipefd[0]);
34 dup2(pipefd[1], STDOUT_FILENO);
35 close(pipefd[1]);
36 char *const cmd[] = {
37 "sh",
38 "-c",
39 state->config->status_command,
40 NULL,
41 };
42 execvp(cmd[0], cmd);
43 return;
44 }
45
46 close(pipefd[1]);
47 state->status_read_fd = pipefd[0];
48 fcntl(state->status_read_fd, F_SETFL, O_NONBLOCK);
49 }
50}
51
52
53void state_setup(struct swaybar_state *state, const char *socket_path, const char *bar_id, int desired_output) {
54 /* initialize state with default values */
55 state_init(state);
56
57 state->output->registry = registry_poll();
58
59 if (!state->output->registry->desktop_shell) {
60 sway_abort("swaybar requires the compositor to support the desktop-shell extension.");
61 }
62
63 /* connect to sway ipc */
64 state->ipc_socketfd = ipc_open_socket(socket_path);
65 state->ipc_event_socketfd = ipc_open_socket(socket_path);
66
67 ipc_bar_init(state, desired_output, bar_id);
68
69 struct output_state *output = state->output->registry->outputs->items[desired_output];
70
71 state->output->window = window_setup(state->output->registry, output->width, 30, false);
72 if (!state->output->window) {
73 sway_abort("Failed to create window.");
74 }
75 desktop_shell_set_panel(state->output->registry->desktop_shell, output->output, state->output->window->surface);
76 desktop_shell_set_panel_position(state->output->registry->desktop_shell, state->config->position);
77
78 /* set font */
79 state->output->window->font = state->config->font;
80
81 /* set window height */
82 set_window_height(state->output->window, state->config->height);
83
84 /* spawn status command */
85 spawn_status_cmd_proc(state);
86}
87
88void state_run(struct swaybar_state *state) {
89 fd_set readfds;
90 int activity;
91 bool dirty = true;
92
93 while (1) {
94 if (dirty) {
95 struct output *output = state->output;
96 if (window_prerender(output->window) && output->window->cairo) {
97 render(output, state->config, state->status);
98 window_render(output->window);
99 if (wl_display_dispatch(output->registry->display) == -1) {
100 break;
101 }
102 }
103 }
104
105 dirty = false;
106 FD_ZERO(&readfds);
107 FD_SET(state->ipc_event_socketfd, &readfds);
108 FD_SET(state->status_read_fd, &readfds);
109
110 activity = select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
111 if (activity < 0) {
112 sway_log(L_ERROR, "polling failed: %d", errno);
113 }
114
115 if (FD_ISSET(state->ipc_event_socketfd, &readfds)) {
116 sway_log(L_DEBUG, "Got IPC event.");
117 dirty = handle_ipc_event(state);
118 }
119
120 if (state->config->status_command && FD_ISSET(state->status_read_fd, &readfds)) {
121 sway_log(L_DEBUG, "Got update from status command.");
122 dirty = handle_status_line(state);
123 }
124 }
125}
126
127void free_workspaces(list_t *workspaces) {
128 int i;
129 for (i = 0; i < workspaces->length; ++i) {
130 struct workspace *ws = workspaces->items[i];
131 free(ws->name);
132 free(ws);
133 }
134 list_free(workspaces);
135}
136
137static void free_output(struct output *output) {
138 window_teardown(output->window);
139 if (output->registry) {
140 registry_teardown(output->registry);
141 }
142
143 free(output->name);
144
145 if (output->workspaces) {
146 free_workspaces(output->workspaces);
147 }
148
149 free(output);
150}
151
152static void terminate_status_command(pid_t pid) {
153 if (pid) {
154 // terminate status_command process
155 int ret = kill(pid, SIGTERM);
156 if (ret != 0) {
157 sway_log(L_ERROR, "Unable to terminate status_command [pid: %d]", pid);
158 } else {
159 int status;
160 waitpid(pid, &status, 0);
161 }
162 }
163}
164
165void state_teardown(struct swaybar_state *state) {
166 free_config(state->config);
167 free_output(state->output);
168 free_status_line(state->status);
169
170 /* close sockets/pipes */
171 if (state->status_read_fd) {
172 close(state->status_read_fd);
173 }
174
175 if (state->ipc_socketfd) {
176 close(state->ipc_socketfd);
177 }
178
179 if (state->ipc_event_socketfd) {
180 close(state->ipc_event_socketfd);
181 }
182
183 /* terminate status command process */
184 terminate_status_command(state->status_command_pid);
185}
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
index a072673b..6b630c49 100644
--- a/swaybar/status_line.c
+++ b/swaybar/status_line.c
@@ -19,7 +19,7 @@ struct {
19 char *parserpos; 19 char *parserpos;
20 bool escape; 20 bool escape;
21 int depth; 21 int depth;
22 int state[I3JSON_MAXDEPTH+1]; 22 int bar[I3JSON_MAXDEPTH+1];
23} i3json_state = { 0, NULL, NULL, NULL, false, 0, { I3JSON_UNKNOWN } }; 23} i3json_state = { 0, NULL, NULL, NULL, false, 0, { I3JSON_UNKNOWN } };
24 24
25static char line[1024]; 25static char line[1024];
@@ -48,7 +48,7 @@ static void free_status_block(void *item) {
48 free(sb); 48 free(sb);
49} 49}
50 50
51static void parse_json(struct swaybar_state *state, const char *text) { 51static void parse_json(struct bar *bar, const char *text) {
52 json_object *results = json_tokener_parse(text); 52 json_object *results = json_tokener_parse(text);
53 if (!results) { 53 if (!results) {
54 sway_log(L_DEBUG, "Failed to parse json"); 54 sway_log(L_DEBUG, "Failed to parse json");
@@ -59,12 +59,12 @@ static void parse_json(struct swaybar_state *state, const char *text) {
59 return; 59 return;
60 } 60 }
61 61
62 if (state->status->block_line) { 62 if (bar->status->block_line) {
63 list_foreach(state->status->block_line, free_status_block); 63 list_foreach(bar->status->block_line, free_status_block);
64 list_free(state->status->block_line); 64 list_free(bar->status->block_line);
65 } 65 }
66 66
67 state->status->block_line = create_list(); 67 bar->status->block_line = create_list();
68 68
69 int i; 69 int i;
70 for (i = 0; i < json_object_array_length(results); ++i) { 70 for (i = 0; i < json_object_array_length(results); ++i) {
@@ -108,7 +108,7 @@ static void parse_json(struct swaybar_state *state, const char *text) {
108 if (color) { 108 if (color) {
109 new->color = parse_color(json_object_get_string(color)); 109 new->color = parse_color(json_object_get_string(color));
110 } else { 110 } else {
111 new->color = state->config->colors.statusline; 111 new->color = bar->config->colors.statusline;
112 } 112 }
113 113
114 if (min_width) { 114 if (min_width) {
@@ -188,18 +188,18 @@ static void parse_json(struct swaybar_state *state, const char *text) {
188 new->border_right = 1; 188 new->border_right = 1;
189 } 189 }
190 190
191 list_add(state->status->block_line, new); 191 list_add(bar->status->block_line, new);
192 } 192 }
193 193
194 json_object_put(results); 194 json_object_put(results);
195} 195}
196 196
197// continue parsing from last parserpos 197// continue parsing from last parserpos
198static int i3json_parse(struct swaybar_state *st) { 198static int i3json_parse(struct bar *bar) {
199 char *c = i3json_state.parserpos; 199 char *c = i3json_state.parserpos;
200 int handled = 0; 200 int handled = 0;
201 while (*c) { 201 while (*c) {
202 if (i3json_state.state[i3json_state.depth] == I3JSON_STRING) { 202 if (i3json_state.bar[i3json_state.depth] == I3JSON_STRING) {
203 if (!i3json_state.escape && *c == '"') { 203 if (!i3json_state.escape && *c == '"') {
204 --i3json_state.depth; 204 --i3json_state.depth;
205 } 205 }
@@ -211,13 +211,13 @@ static int i3json_parse(struct swaybar_state *st) {
211 if (i3json_state.depth > I3JSON_MAXDEPTH) { 211 if (i3json_state.depth > I3JSON_MAXDEPTH) {
212 sway_abort("JSON too deep"); 212 sway_abort("JSON too deep");
213 } 213 }
214 i3json_state.state[i3json_state.depth] = I3JSON_ARRAY; 214 i3json_state.bar[i3json_state.depth] = I3JSON_ARRAY;
215 if (i3json_state.depth == 2) { 215 if (i3json_state.depth == 2) {
216 i3json_state.line_start = c; 216 i3json_state.line_start = c;
217 } 217 }
218 break; 218 break;
219 case ']': 219 case ']':
220 if (i3json_state.state[i3json_state.depth] != I3JSON_ARRAY) { 220 if (i3json_state.bar[i3json_state.depth] != I3JSON_ARRAY) {
221 sway_abort("JSON malformed"); 221 sway_abort("JSON malformed");
222 } 222 }
223 --i3json_state.depth; 223 --i3json_state.depth;
@@ -225,7 +225,7 @@ static int i3json_parse(struct swaybar_state *st) {
225 // c[1] is valid since c[0] != '\0' 225 // c[1] is valid since c[0] != '\0'
226 char p = c[1]; 226 char p = c[1];
227 c[1] = '\0'; 227 c[1] = '\0';
228 parse_json(st, i3json_state.line_start); 228 parse_json(bar, i3json_state.line_start);
229 c[1] = p; 229 c[1] = p;
230 ++handled; 230 ++handled;
231 i3json_state.line_start = c+1; 231 i3json_state.line_start = c+1;
@@ -236,7 +236,7 @@ static int i3json_parse(struct swaybar_state *st) {
236 if (i3json_state.depth > I3JSON_MAXDEPTH) { 236 if (i3json_state.depth > I3JSON_MAXDEPTH) {
237 sway_abort("JSON too deep"); 237 sway_abort("JSON too deep");
238 } 238 }
239 i3json_state.state[i3json_state.depth] = I3JSON_STRING; 239 i3json_state.bar[i3json_state.depth] = I3JSON_STRING;
240 break; 240 break;
241 } 241 }
242 } 242 }
@@ -361,49 +361,49 @@ static void i3json_ensure_free(int min_free) {
361} 361}
362 362
363// append data and parse it. 363// append data and parse it.
364static int i3json_handle_data(struct swaybar_state *st, char *data) { 364static int i3json_handle_data(struct bar *bar, char *data) {
365 int len = strlen(data); 365 int len = strlen(data);
366 i3json_ensure_free(len); 366 i3json_ensure_free(len);
367 strcpy(i3json_state.parserpos, data); 367 strcpy(i3json_state.parserpos, data);
368 return i3json_parse(st); 368 return i3json_parse(bar);
369} 369}
370 370
371// read data from fd and parse it. 371// read data from fd and parse it.
372static int i3json_handle_fd(struct swaybar_state *state) { 372static int i3json_handle_fd(struct bar *bar) {
373 i3json_ensure_free(10240); 373 i3json_ensure_free(10240);
374 // get fresh data at the end of the buffer 374 // get fresh data at the end of the buffer
375 int readlen = read(state->status_read_fd, i3json_state.parserpos, 10239); 375 int readlen = read(bar->status_read_fd, i3json_state.parserpos, 10239);
376 if (readlen < 0) { 376 if (readlen < 0) {
377 return readlen; 377 return readlen;
378 } 378 }
379 i3json_state.parserpos[readlen] = '\0'; 379 i3json_state.parserpos[readlen] = '\0';
380 return i3json_parse(state); 380 return i3json_parse(bar);
381} 381}
382 382
383bool handle_status_line(struct swaybar_state *state) { 383bool handle_status_line(struct bar *bar) {
384 bool dirty = false; 384 bool dirty = false;
385 385
386 switch (state->status->protocol) { 386 switch (bar->status->protocol) {
387 case I3BAR: 387 case I3BAR:
388 sway_log(L_DEBUG, "Got i3bar protocol."); 388 sway_log(L_DEBUG, "Got i3bar protocol.");
389 if (i3json_handle_fd(state) > 0) { 389 if (i3json_handle_fd(bar) > 0) {
390 dirty = true; 390 dirty = true;
391 } 391 }
392 break; 392 break;
393 case TEXT: 393 case TEXT:
394 sway_log(L_DEBUG, "Got text protocol."); 394 sway_log(L_DEBUG, "Got text protocol.");
395 read_line_tail(state->status_read_fd, line, sizeof(line), line_rest); 395 read_line_tail(bar->status_read_fd, line, sizeof(line), line_rest);
396 dirty = true; 396 dirty = true;
397 state->status->text_line = line; 397 bar->status->text_line = line;
398 break; 398 break;
399 case UNDEF: 399 case UNDEF:
400 sway_log(L_DEBUG, "Detecting protocol..."); 400 sway_log(L_DEBUG, "Detecting protocol...");
401 if (read_line_tail(state->status_read_fd, line, sizeof(line), line_rest) < 0) { 401 if (read_line_tail(bar->status_read_fd, line, sizeof(line), line_rest) < 0) {
402 break; 402 break;
403 } 403 }
404 dirty = true; 404 dirty = true;
405 state->status->text_line = line; 405 bar->status->text_line = line;
406 state->status->protocol = TEXT; 406 bar->status->protocol = TEXT;
407 if (line[0] == '{') { 407 if (line[0] == '{') {
408 // detect i3bar json protocol 408 // detect i3bar json protocol
409 json_object *proto = json_tokener_parse(line); 409 json_object *proto = json_tokener_parse(line);
@@ -413,8 +413,8 @@ bool handle_status_line(struct swaybar_state *state) {
413 && json_object_get_int(version) == 1 413 && json_object_get_int(version) == 1
414 ) { 414 ) {
415 sway_log(L_DEBUG, "Switched to i3bar protocol."); 415 sway_log(L_DEBUG, "Switched to i3bar protocol.");
416 state->status->protocol = I3BAR; 416 bar->status->protocol = I3BAR;
417 i3json_handle_data(state, line_rest); 417 i3json_handle_data(bar, line_rest);
418 } 418 }
419 json_object_put(proto); 419 json_object_put(proto);
420 } 420 }
diff --git a/swaybar/status_line.h b/swaybar/status_line.h
index 1d73dd57..273542dc 100644
--- a/swaybar/status_line.h
+++ b/swaybar/status_line.h
@@ -5,7 +5,7 @@
5#include <stdbool.h> 5#include <stdbool.h>
6 6
7#include "list.h" 7#include "list.h"
8#include "state.h" 8#include "bar.h"
9 9
10typedef enum {UNDEF, TEXT, I3BAR} command_protocol; 10typedef enum {UNDEF, TEXT, I3BAR} command_protocol;
11 11
@@ -40,7 +40,7 @@ struct status_line *init_status_line();
40/** 40/**
41 * handle status line activity. 41 * handle status line activity.
42 */ 42 */
43bool handle_status_line(struct swaybar_state *st); 43bool handle_status_line(struct bar *bar);
44 44
45/** 45/**
46 * Free status line struct. 46 * Free status line struct.