aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
authorLibravatar Brian Ashworth <bosrsf04@gmail.com>2019-09-02 21:41:11 -0400
committerLibravatar Drew DeVault <sir@cmpwn.com>2019-09-04 16:48:50 -1000
commit1fd2c6ba498e61f4fe823bf552f9d2fce8612de4 (patch)
tree8e2d9adab3451f1f05c76340d466a442c840e558 /swaybar
parentseatop_default: only focus container on press (diff)
downloadsway-1fd2c6ba498e61f4fe823bf552f9d2fce8612de4.tar.gz
sway-1fd2c6ba498e61f4fe823bf552f9d2fce8612de4.tar.zst
sway-1fd2c6ba498e61f4fe823bf552f9d2fce8612de4.zip
swaybar: complete barconfig_update event handling
This adds complete support for the barconfig_update ipc event. This also changes the bar command and subcommand handlers to correctly emit the event. This makes it so all bar subcommands other than id and swaybar_command are dynamically changeable at runtime. sway-bar.5 has been updated accordingly
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/bar.c35
-rw-r--r--swaybar/config.c4
-rw-r--r--swaybar/ipc.c367
-rw-r--r--swaybar/status_line.c3
4 files changed, 237 insertions, 172 deletions
diff --git a/swaybar/bar.c b/swaybar/bar.c
index 35e1662b..efd0da4b 100644
--- a/swaybar/bar.c
+++ b/swaybar/bar.c
@@ -126,7 +126,7 @@ static void add_layer_surface(struct swaybar_output *output) {
126 } 126 }
127} 127}
128 128
129static void destroy_layer_surface(struct swaybar_output *output) { 129void destroy_layer_surface(struct swaybar_output *output) {
130 if (!output->layer_surface) { 130 if (!output->layer_surface) {
131 return; 131 return;
132 } 132 }
@@ -181,7 +181,7 @@ bool determine_bar_visibility(struct swaybar *bar, bool moving_layer) {
181} 181}
182 182
183static bool bar_uses_output(struct swaybar_output *output) { 183static bool bar_uses_output(struct swaybar_output *output) {
184 if (output->bar->config->all_outputs) { 184 if (wl_list_empty(&output->bar->config->outputs)) {
185 return true; 185 return true;
186 } 186 }
187 char *identifier = output->identifier; 187 char *identifier = output->identifier;
@@ -256,20 +256,27 @@ static void xdg_output_handle_done(void *data,
256 struct swaybar_output *output = data; 256 struct swaybar_output *output = data;
257 struct swaybar *bar = output->bar; 257 struct swaybar *bar = output->bar;
258 258
259 if (!wl_list_empty(&output->link)) {
260 return;
261 }
262
259 assert(output->name != NULL); 263 assert(output->name != NULL);
260 if (!bar_uses_output(output)) { 264 if (!bar_uses_output(output)) {
261 swaybar_output_free(output); 265 wl_list_remove(&output->link);
266 wl_list_insert(&bar->unused_outputs, &output->link);
262 return; 267 return;
263 } 268 }
264 269
265 if (wl_list_empty(&output->link)) { 270 wl_list_remove(&output->link);
266 wl_list_remove(&output->link); 271 wl_list_insert(&bar->outputs, &output->link);
267 wl_list_insert(&bar->outputs, &output->link);
268 272
269 output->surface = wl_compositor_create_surface(bar->compositor); 273 output->surface = wl_compositor_create_surface(bar->compositor);
270 assert(output->surface); 274 assert(output->surface);
271 275
272 determine_bar_visibility(bar, false); 276 determine_bar_visibility(bar, false);
277
278 if (bar->running && bar->config->workspace_buttons) {
279 ipc_get_workspaces(bar);
273 } 280 }
274} 281}
275 282
@@ -373,6 +380,12 @@ static void handle_global_remove(void *data, struct wl_registry *registry,
373 return; 380 return;
374 } 381 }
375 } 382 }
383 wl_list_for_each_safe(output, tmp, &bar->unused_outputs, link) {
384 if (output->wl_name == name) {
385 swaybar_output_free(output);
386 return;
387 }
388 }
376 struct swaybar_seat *seat, *tmp_seat; 389 struct swaybar_seat *seat, *tmp_seat;
377 wl_list_for_each_safe(seat, tmp_seat, &bar->seats, link) { 390 wl_list_for_each_safe(seat, tmp_seat, &bar->seats, link) {
378 if (seat->wl_name == name) { 391 if (seat->wl_name == name) {
@@ -391,6 +404,7 @@ bool bar_setup(struct swaybar *bar, const char *socket_path) {
391 bar->visible = true; 404 bar->visible = true;
392 bar->config = init_config(); 405 bar->config = init_config();
393 wl_list_init(&bar->outputs); 406 wl_list_init(&bar->outputs);
407 wl_list_init(&bar->unused_outputs);
394 wl_list_init(&bar->seats); 408 wl_list_init(&bar->seats);
395 bar->eventloop = loop_create(); 409 bar->eventloop = loop_create();
396 410
@@ -458,7 +472,7 @@ static void ipc_in(int fd, short mask, void *data) {
458 } 472 }
459} 473}
460 474
461static void status_in(int fd, short mask, void *data) { 475void status_in(int fd, short mask, void *data) {
462 struct swaybar *bar = data; 476 struct swaybar *bar = data;
463 if (mask & (POLLHUP | POLLERR)) { 477 if (mask & (POLLHUP | POLLERR)) {
464 status_error(bar->status, "[error reading from status command]"); 478 status_error(bar->status, "[error reading from status command]");
@@ -510,6 +524,7 @@ void bar_teardown(struct swaybar *bar) {
510 destroy_tray(bar->tray); 524 destroy_tray(bar->tray);
511#endif 525#endif
512 free_outputs(&bar->outputs); 526 free_outputs(&bar->outputs);
527 free_outputs(&bar->unused_outputs);
513 free_seats(&bar->seats); 528 free_seats(&bar->seats);
514 if (bar->config) { 529 if (bar->config) {
515 free_config(bar->config); 530 free_config(bar->config);
diff --git a/swaybar/config.c b/swaybar/config.c
index 6e36573c..52297310 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -84,7 +84,7 @@ struct swaybar_config *init_config(void) {
84 return config; 84 return config;
85} 85}
86 86
87static void free_binding(struct swaybar_binding *binding) { 87void free_binding(struct swaybar_binding *binding) {
88 if (!binding) { 88 if (!binding) {
89 return; 89 return;
90 } 90 }
@@ -93,7 +93,7 @@ static void free_binding(struct swaybar_binding *binding) {
93} 93}
94 94
95#if HAVE_TRAY 95#if HAVE_TRAY
96static void free_tray_binding(struct tray_binding *binding) { 96void free_tray_binding(struct tray_binding *binding) {
97 if (!binding) { 97 if (!binding) {
98 return; 98 return;
99 } 99 }
diff --git a/swaybar/ipc.c b/swaybar/ipc.c
index a096f01a..afaffb04 100644
--- a/swaybar/ipc.c
+++ b/swaybar/ipc.c
@@ -1,15 +1,21 @@
1#define _POSIX_C_SOURCE 200809 1#define _POSIX_C_SOURCE 200809
2#include <limits.h> 2#include <limits.h>
3#include <poll.h>
3#include <stdio.h> 4#include <stdio.h>
4#include <string.h> 5#include <string.h>
5#include <strings.h> 6#include <strings.h>
6#include <json.h> 7#include <json.h>
7#include "swaybar/config.h" 8#include "swaybar/config.h"
8#include "swaybar/ipc.h" 9#include "swaybar/ipc.h"
10#include "swaybar/status_line.h"
11#if HAVE_TRAY
12#include "swaybar/tray/tray.h"
13#endif
9#include "config.h" 14#include "config.h"
10#include "ipc-client.h" 15#include "ipc-client.h"
11#include "list.h" 16#include "list.h"
12#include "log.h" 17#include "log.h"
18#include "loop.h"
13#include "util.h" 19#include "util.h"
14 20
15void ipc_send_workspace_command(struct swaybar *bar, const char *ws) { 21void ipc_send_workspace_command(struct swaybar *bar, const char *ws) {
@@ -169,75 +175,58 @@ static bool ipc_parse_config(
169 json_object *success; 175 json_object *success;
170 if (json_object_object_get_ex(bar_config, "success", &success) 176 if (json_object_object_get_ex(bar_config, "success", &success)
171 && !json_object_get_boolean(success)) { 177 && !json_object_get_boolean(success)) {
172 sway_log(SWAY_ERROR, "No bar with that ID. Use 'swaymsg -t get_bar_config to get the available bar configs."); 178 sway_log(SWAY_ERROR, "No bar with that ID. Use 'swaymsg -t "
179 "get_bar_config' to get the available bar configs.");
173 json_object_put(bar_config); 180 json_object_put(bar_config);
174 return false; 181 return false;
175 } 182 }
176 json_object *markup, *mode, *hidden_state, *position, *status_command; 183
177 json_object *font, *gaps, *bar_height, *wrap_scroll, *workspace_buttons; 184 json_object *bar_height = json_object_object_get(bar_config, "bar_height");
178 json_object *strip_workspace_numbers, *strip_workspace_name; 185 if (bar_height) {
179 json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol; 186 config->height = json_object_get_int(bar_height);
180 json_object *outputs, *bindings, *status_padding, *status_edge_padding;
181 json_object_object_get_ex(bar_config, "mode", &mode);
182 json_object_object_get_ex(bar_config, "hidden_state", &hidden_state);
183 json_object_object_get_ex(bar_config, "position", &position);
184 json_object_object_get_ex(bar_config, "status_command", &status_command);
185 json_object_object_get_ex(bar_config, "font", &font);
186 json_object_object_get_ex(bar_config, "gaps", &gaps);
187 json_object_object_get_ex(bar_config, "bar_height", &bar_height);
188 json_object_object_get_ex(bar_config, "wrap_scroll", &wrap_scroll);
189 json_object_object_get_ex(bar_config, "workspace_buttons", &workspace_buttons);
190 json_object_object_get_ex(bar_config, "strip_workspace_numbers", &strip_workspace_numbers);
191 json_object_object_get_ex(bar_config, "strip_workspace_name", &strip_workspace_name);
192 json_object_object_get_ex(bar_config, "binding_mode_indicator", &binding_mode_indicator);
193 json_object_object_get_ex(bar_config, "verbose", &verbose);
194 json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol);
195 json_object_object_get_ex(bar_config, "colors", &colors);
196 json_object_object_get_ex(bar_config, "outputs", &outputs);
197 json_object_object_get_ex(bar_config, "pango_markup", &markup);
198 json_object_object_get_ex(bar_config, "bindings", &bindings);
199 json_object_object_get_ex(bar_config, "status_padding", &status_padding);
200 json_object_object_get_ex(bar_config, "status_edge_padding",
201 &status_edge_padding);
202 if (status_command) {
203 free(config->status_command);
204 config->status_command = strdup(json_object_get_string(status_command));
205 }
206 if (position) {
207 config->position = parse_position(json_object_get_string(position));
208 }
209 if (font) {
210 free(config->font);
211 config->font = parse_font(json_object_get_string(font));
212 }
213 if (sep_symbol) {
214 free(config->sep_symbol);
215 config->sep_symbol = strdup(json_object_get_string(sep_symbol));
216 }
217 if (strip_workspace_numbers) {
218 config->strip_workspace_numbers = json_object_get_boolean(strip_workspace_numbers);
219 }
220 if (strip_workspace_name) {
221 config->strip_workspace_name = json_object_get_boolean(strip_workspace_name);
222 } 187 }
188
189 json_object *binding_mode_indicator =
190 json_object_object_get(bar_config, "binding_mode_indicator");
223 if (binding_mode_indicator) { 191 if (binding_mode_indicator) {
224 config->binding_mode_indicator = json_object_get_boolean(binding_mode_indicator); 192 config->binding_mode_indicator =
193 json_object_get_boolean(binding_mode_indicator);
225 } 194 }
226 if (wrap_scroll) { 195
227 config->wrap_scroll = json_object_get_boolean(wrap_scroll); 196 json_object *bindings = json_object_object_get(bar_config, "bindings");
228 } 197 while (config->bindings->length) {
229 if (workspace_buttons) { 198 struct swaybar_binding *binding = config->bindings->items[0];
230 config->workspace_buttons = json_object_get_boolean(workspace_buttons); 199 list_del(config->bindings, 0);
200 free_binding(binding);
231 } 201 }
232 if (bar_height) { 202 if (bindings) {
233 config->height = json_object_get_int(bar_height); 203 int length = json_object_array_length(bindings);
204 for (int i = 0; i < length; ++i) {
205 json_object *bindobj = json_object_array_get_idx(bindings, i);
206 struct swaybar_binding *binding =
207 calloc(1, sizeof(struct swaybar_binding));
208 binding->button = json_object_get_int(
209 json_object_object_get(bindobj, "event_code"));
210 binding->command = strdup(json_object_get_string(
211 json_object_object_get(bindobj, "command")));
212 binding->release = json_object_get_boolean(
213 json_object_object_get(bindobj, "release"));
214 list_add(config->bindings, binding);
215 }
234 } 216 }
235 if (status_padding) { 217
236 config->status_padding = json_object_get_int(status_padding); 218 json_object *colors = json_object_object_get(bar_config, "colors");
219 if (colors) {
220 ipc_parse_colors(config, colors);
237 } 221 }
238 if (status_edge_padding) { 222
239 config->status_edge_padding = json_object_get_int(status_edge_padding); 223 json_object *font = json_object_object_get(bar_config, "font");
224 if (font) {
225 free(config->font);
226 config->font = parse_font(json_object_get_string(font));
240 } 227 }
228
229 json_object *gaps = json_object_object_get(bar_config, "gaps");
241 if (gaps) { 230 if (gaps) {
242 json_object *top = json_object_object_get(gaps, "top"); 231 json_object *top = json_object_object_get(gaps, "top");
243 if (top) { 232 if (top) {
@@ -256,33 +245,21 @@ static bool ipc_parse_config(
256 config->gaps.left = json_object_get_int(left); 245 config->gaps.left = json_object_get_int(left);
257 } 246 }
258 } 247 }
259 if (markup) { 248
260 config->pango_markup = json_object_get_boolean(markup); 249 json_object *hidden_state =
261 } 250 json_object_object_get(bar_config, "hidden_state");
262 if (bindings) {
263 int length = json_object_array_length(bindings);
264 for (int i = 0; i < length; ++i) {
265 json_object *bindobj = json_object_array_get_idx(bindings, i);
266 struct swaybar_binding *binding =
267 calloc(1, sizeof(struct swaybar_binding));
268 binding->button = json_object_get_int(
269 json_object_object_get(bindobj, "event_code"));
270 binding->command = strdup(json_object_get_string(
271 json_object_object_get(bindobj, "command")));
272 binding->release = json_object_get_boolean(
273 json_object_object_get(bindobj, "release"));
274 list_add(config->bindings, binding);
275 }
276 }
277 if (hidden_state) { 251 if (hidden_state) {
278 free(config->hidden_state); 252 free(config->hidden_state);
279 config->hidden_state = strdup(json_object_get_string(hidden_state)); 253 config->hidden_state = strdup(json_object_get_string(hidden_state));
280 } 254 }
255
256 json_object *mode = json_object_object_get(bar_config, "mode");
281 if (mode) { 257 if (mode) {
282 free(config->mode); 258 free(config->mode);
283 config->mode = strdup(json_object_get_string(mode)); 259 config->mode = strdup(json_object_get_string(mode));
284 } 260 }
285 261
262 json_object *outputs = json_object_object_get(bar_config, "outputs");
286 struct config_output *output, *tmp; 263 struct config_output *output, *tmp;
287 wl_list_for_each_safe(output, tmp, &config->outputs, link) { 264 wl_list_for_each_safe(output, tmp, &config->outputs, link) {
288 wl_list_remove(&output->link); 265 wl_list_remove(&output->link);
@@ -295,40 +272,115 @@ static bool ipc_parse_config(
295 json_object *output = json_object_array_get_idx(outputs, i); 272 json_object *output = json_object_array_get_idx(outputs, i);
296 const char *name = json_object_get_string(output); 273 const char *name = json_object_get_string(output);
297 if (strcmp("*", name) == 0) { 274 if (strcmp("*", name) == 0) {
298 config->all_outputs = true; 275 struct config_output *coutput, *tmp;
276 wl_list_for_each_safe(coutput, tmp, &config->outputs, link) {
277 wl_list_remove(&coutput->link);
278 free(coutput->name);
279 free(coutput);
280 }
299 break; 281 break;
300 } 282 }
301 struct config_output *coutput = calloc( 283 struct config_output *coutput = calloc(
302 1, sizeof(struct config_output)); 284 1, sizeof(struct config_output));
303 coutput->name = strdup(name); 285 coutput->name = strdup(name);
304 coutput->index = SIZE_MAX;
305 wl_list_insert(&config->outputs, &coutput->link); 286 wl_list_insert(&config->outputs, &coutput->link);
306 } 287 }
307 } else {
308 config->all_outputs = true;
309 } 288 }
310 289
311 if (colors) { 290 json_object *pango_markup =
312 ipc_parse_colors(config, colors); 291 json_object_object_get(bar_config, "pango_markup");
292 if (pango_markup) {
293 config->pango_markup = json_object_get_boolean(pango_markup);
294 }
295
296 json_object *position = json_object_object_get(bar_config, "position");
297 if (position) {
298 config->position = parse_position(json_object_get_string(position));
299 }
300
301 json_object *separator_symbol =
302 json_object_object_get(bar_config, "separator_symbol");
303 if (separator_symbol) {
304 free(config->sep_symbol);
305 config->sep_symbol = strdup(json_object_get_string(separator_symbol));
306 }
307
308 json_object *status_command =
309 json_object_object_get(bar_config, "status_command");
310 if (status_command) {
311 const char *command = json_object_get_string(status_command);
312 free(config->status_command);
313 config->status_command = strdup(command);
314 }
315
316 json_object *status_edge_padding =
317 json_object_object_get(bar_config, "status_edge_padding");
318 if (status_edge_padding) {
319 config->status_edge_padding = json_object_get_int(status_edge_padding);
320 }
321
322 json_object *status_padding =
323 json_object_object_get(bar_config, "status_padding");
324 if (status_padding) {
325 config->status_padding = json_object_get_int(status_padding);
326 }
327
328 json_object *strip_workspace_name =
329 json_object_object_get(bar_config, "strip_workspace_name");
330 if (strip_workspace_name) {
331 config->strip_workspace_name =
332 json_object_get_boolean(strip_workspace_name);
313 } 333 }
314 334
335 json_object *strip_workspace_numbers =
336 json_object_object_get(bar_config, "strip_workspace_numbers");
337 if (strip_workspace_numbers) {
338 config->strip_workspace_numbers =
339 json_object_get_boolean(strip_workspace_numbers);
340 }
341
342 json_object *workspace_buttons =
343 json_object_object_get(bar_config, "workspace_buttons");
344 if (workspace_buttons) {
345 config->workspace_buttons = json_object_get_boolean(workspace_buttons);
346 }
347
348 json_object *wrap_scroll = json_object_object_get(bar_config, "wrap_scroll");
349 if (wrap_scroll) {
350 config->wrap_scroll = json_object_get_boolean(wrap_scroll);
351 }
315#if HAVE_TRAY 352#if HAVE_TRAY
316 json_object *tray_outputs, *tray_padding, *tray_bindings, *icon_theme; 353 json_object *tray_outputs, *tray_padding, *tray_bindings, *icon_theme;
317 354
355 if (config->tray_outputs && config->tray_outputs->length) {
356 list_free_items_and_destroy(config->tray_outputs);
357 }
318 if ((json_object_object_get_ex(bar_config, "tray_outputs", &tray_outputs))) { 358 if ((json_object_object_get_ex(bar_config, "tray_outputs", &tray_outputs))) {
319 config->tray_outputs = create_list(); 359 config->tray_outputs = create_list();
320 int length = json_object_array_length(tray_outputs); 360 int length = json_object_array_length(tray_outputs);
321 for (int i = 0; i < length; ++i) { 361 for (int i = 0; i < length; ++i) {
322 json_object *o = json_object_array_get_idx(tray_outputs, i); 362 json_object *output= json_object_array_get_idx(tray_outputs, i);
323 list_add(config->tray_outputs, strdup(json_object_get_string(o))); 363 const char *name = json_object_get_string(output);
364 if (strcmp(name, "none") == 0) {
365 config->tray_hidden = true;
366 list_free_items_and_destroy(config->tray_outputs);
367 config->tray_outputs = create_list();
368 break;
369 }
370 list_add(config->tray_outputs, strdup(name));
324 } 371 }
325 config->tray_hidden = strcmp(config->tray_outputs->items[0], "none") == 0;
326 } 372 }
327 373
328 if ((json_object_object_get_ex(bar_config, "tray_padding", &tray_padding))) { 374 if ((json_object_object_get_ex(bar_config, "tray_padding", &tray_padding))) {
329 config->tray_padding = json_object_get_int(tray_padding); 375 config->tray_padding = json_object_get_int(tray_padding);
330 } 376 }
331 377
378 struct tray_binding *tray_bind = NULL, *tmp_tray_bind = NULL;
379 wl_list_for_each_safe(tray_bind, tmp_tray_bind, &config->tray_bindings,
380 link) {
381 wl_list_remove(&tray_bind->link);
382 free_tray_binding(tray_bind);
383 }
332 if ((json_object_object_get_ex(bar_config, "tray_bindings", &tray_bindings))) { 384 if ((json_object_object_get_ex(bar_config, "tray_bindings", &tray_bindings))) {
333 int length = json_object_array_length(tray_bindings); 385 int length = json_object_array_length(tray_bindings);
334 for (int i = 0; i < length; ++i) { 386 for (int i = 0; i < length; ++i) {
@@ -423,41 +475,6 @@ bool ipc_get_workspaces(struct swaybar *bar) {
423 return determine_bar_visibility(bar, false); 475 return determine_bar_visibility(bar, false);
424} 476}
425 477
426static void ipc_get_outputs(struct swaybar *bar) {
427 uint32_t len = 0;
428 char *res = ipc_single_command(bar->ipc_socketfd,
429 IPC_GET_OUTPUTS, NULL, &len);
430 json_object *outputs = json_tokener_parse(res);
431 for (size_t i = 0; i < json_object_array_length(outputs); ++i) {
432 json_object *output = json_object_array_get_idx(outputs, i);
433 json_object *output_name, *output_active;
434 json_object_object_get_ex(output, "name", &output_name);
435 json_object_object_get_ex(output, "active", &output_active);
436 const char *name = json_object_get_string(output_name);
437 bool active = json_object_get_boolean(output_active);
438 if (!active) {
439 continue;
440 }
441 if (bar->config->all_outputs) {
442 struct config_output *coutput =
443 calloc(1, sizeof(struct config_output));
444 coutput->name = strdup(name);
445 coutput->index = i;
446 wl_list_insert(&bar->config->outputs, &coutput->link);
447 } else {
448 struct config_output *coutput;
449 wl_list_for_each(coutput, &bar->config->outputs, link) {
450 if (strcmp(name, coutput->name) == 0) {
451 coutput->index = i;
452 break;
453 }
454 }
455 }
456 }
457 json_object_put(outputs);
458 free(res);
459}
460
461void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind) { 478void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind) {
462 sway_log(SWAY_DEBUG, "Executing binding for button %u (release=%d): `%s`", 479 sway_log(SWAY_DEBUG, "Executing binding for button %u (release=%d): `%s`",
463 bind->button, bind->release, bind->command); 480 bind->button, bind->release, bind->command);
@@ -475,7 +492,6 @@ bool ipc_initialize(struct swaybar *bar) {
475 return false; 492 return false;
476 } 493 }
477 free(res); 494 free(res);
478 ipc_get_outputs(bar);
479 495
480 struct swaybar_config *config = bar->config; 496 struct swaybar_config *config = bar->config;
481 char subscribe[128]; // suitably large buffer 497 char subscribe[128]; // suitably large buffer
@@ -509,56 +525,87 @@ static bool handle_bar_state_update(struct swaybar *bar, json_object *event) {
509 return determine_bar_visibility(bar, false); 525 return determine_bar_visibility(bar, false);
510} 526}
511 527
512static bool handle_barconfig_update(struct swaybar *bar, 528static bool handle_barconfig_update(struct swaybar *bar, const char *payload,
513 json_object *json_config) { 529 json_object *json_config) {
514 json_object *json_id; 530 json_object *json_id = json_object_object_get(json_config, "id");
515 json_object_object_get_ex(json_config, "id", &json_id);
516 const char *id = json_object_get_string(json_id); 531 const char *id = json_object_get_string(json_id);
517 if (strcmp(id, bar->id) != 0) { 532 if (strcmp(id, bar->id) != 0) {
518 return false; 533 return false;
519 } 534 }
520 535
521 struct swaybar_config *config = bar->config; 536 struct swaybar_config *newcfg = init_config();
537 ipc_parse_config(newcfg, payload);
522 538
523 json_object *json_state; 539 struct swaybar_config *oldcfg = bar->config;
524 json_object_object_get_ex(json_config, "hidden_state", &json_state); 540 bar->config = newcfg;
525 const char *new_state = json_object_get_string(json_state); 541
526 char *old_state = config->hidden_state; 542 struct swaybar_output *output, *tmp_output;
527 if (strcmp(new_state, old_state) != 0) { 543 wl_list_for_each_safe(output, tmp_output, &bar->outputs, link) {
528 sway_log(SWAY_DEBUG, "Changing bar hidden state to %s", new_state); 544 bool found = wl_list_empty(&newcfg->outputs);
529 free(old_state); 545 struct config_output *coutput;
530 config->hidden_state = strdup(new_state); 546 wl_list_for_each(coutput, &newcfg->outputs, link) {
531 return determine_bar_visibility(bar, false); 547 if (strcmp(coutput->name, output->name) == 0 ||
532 } 548 strcmp(coutput->name, output->identifier) == 0) {
533 549 found = true;
534 free(config->mode); 550 break;
535 json_object *json_mode; 551 }
536 json_object_object_get_ex(json_config, "mode", &json_mode);
537 config->mode = strdup(json_object_get_string(json_mode));
538 sway_log(SWAY_DEBUG, "Changing bar mode to %s", config->mode);
539
540 json_object *gaps;
541 json_object_object_get_ex(json_config, "gaps", &gaps);
542 if (gaps) {
543 json_object *top = json_object_object_get(gaps, "top");
544 if (top) {
545 config->gaps.top = json_object_get_int(top);
546 } 552 }
547 json_object *right = json_object_object_get(gaps, "right"); 553 if (!found) {
548 if (right) { 554 destroy_layer_surface(output);
549 config->gaps.right = json_object_get_int(right); 555 wl_list_remove(&output->link);
556 wl_list_insert(&bar->unused_outputs, &output->link);
557 } else if (!oldcfg->font || !newcfg->font ||
558 strcmp(oldcfg->font, newcfg->font) != 0) {
559 output->height = 0; // force update height
550 } 560 }
551 json_object *bottom = json_object_object_get(gaps, "bottom"); 561 }
552 if (bottom) { 562 wl_list_for_each_safe(output, tmp_output, &bar->unused_outputs, link) {
553 config->gaps.bottom = json_object_get_int(bottom); 563 bool found = wl_list_empty(&newcfg->outputs);
564 struct config_output *coutput;
565 wl_list_for_each(coutput, &newcfg->outputs, link) {
566 if (strcmp(coutput->name, output->name) == 0 ||
567 strcmp(coutput->name, output->identifier) == 0) {
568 found = true;
569 break;
570 }
554 } 571 }
555 json_object *left = json_object_object_get(gaps, "left"); 572 if (found) {
556 if (left) { 573 wl_list_remove(&output->link);
557 config->gaps.left = json_object_get_int(left); 574 wl_list_insert(&bar->outputs, &output->link);
558 } 575 }
559 } 576 }
560 577
561 return determine_bar_visibility(bar, true); 578 if (bar->status && (!newcfg->status_command ||
579 strcmp(newcfg->status_command, oldcfg->status_command) != 0)) {
580 status_line_free(bar->status);
581 bar->status = NULL;
582 }
583 if (!bar->status && newcfg->status_command) {
584 bar->status = status_line_init(newcfg->status_command);
585 bar->status->bar = bar;
586 loop_add_fd(bar->eventloop, bar->status->read_fd, POLLIN,
587 status_in, bar);
588 }
589
590#if HAVE_TRAY
591 if (oldcfg->tray_hidden && !newcfg->tray_hidden) {
592 bar->tray = create_tray(bar);
593 loop_add_fd(bar->eventloop, bar->tray->fd, POLLIN, tray_in,
594 bar->tray->bus);
595 } else if (bar->tray && newcfg->tray_hidden) {
596 loop_remove_fd(bar->eventloop, bar->tray->fd);
597 destroy_tray(bar->tray);
598 bar->tray = NULL;
599 }
600#endif
601
602 if (newcfg->workspace_buttons) {
603 ipc_get_workspaces(bar);
604 }
605
606 free_config(oldcfg);
607 determine_bar_visibility(bar, true);
608 return true;
562} 609}
563 610
564bool handle_ipc_readable(struct swaybar *bar) { 611bool handle_ipc_readable(struct swaybar *bar) {
@@ -599,7 +646,7 @@ bool handle_ipc_readable(struct swaybar *bar) {
599 break; 646 break;
600 } 647 }
601 case IPC_EVENT_BARCONFIG_UPDATE: 648 case IPC_EVENT_BARCONFIG_UPDATE:
602 bar_is_dirty = handle_barconfig_update(bar, result); 649 bar_is_dirty = handle_barconfig_update(bar, resp->payload, result);
603 break; 650 break;
604 case IPC_EVENT_BAR_STATE_UPDATE: 651 case IPC_EVENT_BAR_STATE_UPDATE:
605 bar_is_dirty = handle_bar_state_update(bar, result); 652 bar_is_dirty = handle_bar_state_update(bar, result);
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
index 342f981e..2a9e1da8 100644
--- a/swaybar/status_line.c
+++ b/swaybar/status_line.c
@@ -5,6 +5,8 @@
5#include <stdlib.h> 5#include <stdlib.h>
6#include <string.h> 6#include <string.h>
7#include <stdio.h> 7#include <stdio.h>
8#include <sys/types.h>
9#include <sys/wait.h>
8#include <unistd.h> 10#include <unistd.h>
9#include "log.h" 11#include "log.h"
10#include "loop.h" 12#include "loop.h"
@@ -174,6 +176,7 @@ struct status_line *status_line_init(char *cmd) {
174void status_line_free(struct status_line *status) { 176void status_line_free(struct status_line *status) {
175 status_line_close_fds(status); 177 status_line_close_fds(status);
176 kill(status->pid, SIGTERM); 178 kill(status->pid, SIGTERM);
179 waitpid(status->pid, NULL, 0);
177 if (status->protocol == PROTOCOL_I3BAR) { 180 if (status->protocol == PROTOCOL_I3BAR) {
178 struct i3bar_block *block, *tmp; 181 struct i3bar_block *block, *tmp;
179 wl_list_for_each_safe(block, tmp, &status->blocks, link) { 182 wl_list_for_each_safe(block, tmp, &status->blocks, link) {