summaryrefslogtreecommitdiffstats
path: root/swaybar
diff options
context:
space:
mode:
Diffstat (limited to 'swaybar')
-rw-r--r--swaybar/bar.c102
-rw-r--r--swaybar/config.c4
-rw-r--r--swaybar/ipc.c128
-rw-r--r--swaybar/main.c8
-rw-r--r--swaybar/render.c32
-rw-r--r--swaybar/status_line.c14
6 files changed, 214 insertions, 74 deletions
diff --git a/swaybar/bar.c b/swaybar/bar.c
index 5b7fea71..9f72c94c 100644
--- a/swaybar/bar.c
+++ b/swaybar/bar.c
@@ -32,9 +32,21 @@
32 32
33static void bar_init(struct swaybar *bar) { 33static void bar_init(struct swaybar *bar) {
34 bar->config = init_config(); 34 bar->config = init_config();
35 bar->visible = true;
35 wl_list_init(&bar->outputs); 36 wl_list_init(&bar->outputs);
36} 37}
37 38
39void free_hotspots(struct wl_list *list) {
40 struct swaybar_hotspot *hotspot, *tmp;
41 wl_list_for_each_safe(hotspot, tmp, list, link) {
42 wl_list_remove(&hotspot->link);
43 if (hotspot->destroy) {
44 hotspot->destroy(hotspot->data);
45 }
46 free(hotspot);
47 }
48}
49
38void free_workspaces(struct wl_list *list) { 50void free_workspaces(struct wl_list *list) {
39 struct swaybar_workspace *ws, *tmp; 51 struct swaybar_workspace *ws, *tmp;
40 wl_list_for_each_safe(ws, tmp, list, link) { 52 wl_list_for_each_safe(ws, tmp, list, link) {
@@ -59,14 +71,8 @@ static void swaybar_output_free(struct swaybar_output *output) {
59 wl_output_destroy(output->output); 71 wl_output_destroy(output->output);
60 destroy_buffer(&output->buffers[0]); 72 destroy_buffer(&output->buffers[0]);
61 destroy_buffer(&output->buffers[1]); 73 destroy_buffer(&output->buffers[1]);
74 free_hotspots(&output->hotspots);
62 free_workspaces(&output->workspaces); 75 free_workspaces(&output->workspaces);
63 struct swaybar_hotspot *hotspot, *hotspot_tmp;
64 wl_list_for_each_safe(hotspot, hotspot_tmp, &output->hotspots, link) {
65 if (hotspot->destroy) {
66 hotspot->destroy(hotspot->data);
67 }
68 free(hotspot);
69 }
70 wl_list_remove(&output->link); 76 wl_list_remove(&output->link);
71 free(output->name); 77 free(output->name);
72 free(output); 78 free(output);
@@ -75,9 +81,7 @@ static void swaybar_output_free(struct swaybar_output *output) {
75static void set_output_dirty(struct swaybar_output *output) { 81static void set_output_dirty(struct swaybar_output *output) {
76 if (output->frame_scheduled) { 82 if (output->frame_scheduled) {
77 output->dirty = true; 83 output->dirty = true;
78 return; 84 } else if (output->surface) {
79 }
80 if (output->surface) {
81 render_frame(output); 85 render_frame(output);
82 } 86 }
83} 87}
@@ -335,21 +339,68 @@ const struct wl_seat_listener seat_listener = {
335}; 339};
336 340
337static void add_layer_surface(struct swaybar_output *output) { 341static void add_layer_surface(struct swaybar_output *output) {
338 if (output->surface != NULL) { 342 if (output->layer_surface) {
339 return; 343 return;
340 } 344 }
341 struct swaybar *bar = output->bar; 345 struct swaybar *bar = output->bar;
342 346
343 output->surface = wl_compositor_create_surface(bar->compositor); 347 struct swaybar_config *config = bar->config;
344 assert(output->surface); 348 bool hidden = strcmp(config->mode, "hide") == 0;
345 output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( 349 output->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
346 bar->layer_shell, output->surface, output->output, 350 bar->layer_shell, output->surface, output->output,
351 hidden ? ZWLR_LAYER_SHELL_V1_LAYER_TOP :
347 ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); 352 ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel");
348 assert(output->layer_surface); 353 assert(output->layer_surface);
349 zwlr_layer_surface_v1_add_listener(output->layer_surface, 354 zwlr_layer_surface_v1_add_listener(output->layer_surface,
350 &layer_surface_listener, output); 355 &layer_surface_listener, output);
351 zwlr_layer_surface_v1_set_anchor(output->layer_surface, 356
352 bar->config->position); 357 zwlr_layer_surface_v1_set_anchor(output->layer_surface, config->position);
358 if (hidden) {
359 zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1);
360 }
361}
362
363static void destroy_layer_surface(struct swaybar_output *output) {
364 if (!output->layer_surface) {
365 return;
366 }
367 zwlr_layer_surface_v1_destroy(output->layer_surface);
368 wl_surface_attach(output->surface, NULL, 0, 0); // detach buffer
369 output->layer_surface = NULL;
370 output->width = 0;
371 output->frame_scheduled = false;
372}
373
374bool determine_bar_visibility(struct swaybar *bar, bool moving_layer) {
375 struct swaybar_config *config = bar->config;
376 bool visible = !(strcmp(config->mode, "invisible") == 0 ||
377 (strcmp(config->mode, config->hidden_state) == 0 // both "hide"
378 && !bar->visible_by_modifier && !bar->visible_by_urgency));
379
380 struct swaybar_output *output;
381 if (visible == bar->visible) {
382 if (visible && moving_layer) {
383 // need to destroy layer surface to move to a different layer
384 wl_list_for_each(output, &bar->outputs, link) {
385 destroy_layer_surface(output);
386 add_layer_surface(output);
387 }
388 }
389 } else {
390 bar->visible = visible;
391 wl_list_for_each(output, &bar->outputs, link) {
392 if (visible) {
393 add_layer_surface(output);
394 } else {
395 destroy_layer_surface(output);
396 }
397 }
398 wlr_log(WLR_DEBUG, "Sending %s signal to status command",
399 visible ? "cont" : "stop");
400 kill(bar->status->pid,
401 visible ? bar->status->cont_signal : bar->status->stop_signal);
402 }
403 return visible;
353} 404}
354 405
355static bool bar_uses_output(struct swaybar *bar, const char *name) { 406static bool bar_uses_output(struct swaybar *bar, const char *name) {
@@ -420,8 +471,11 @@ static void xdg_output_handle_done(void *data,
420 wl_list_remove(&output->link); 471 wl_list_remove(&output->link);
421 wl_list_insert(&bar->outputs, &output->link); 472 wl_list_insert(&bar->outputs, &output->link);
422 473
423 add_layer_surface(output); 474 output->surface = wl_compositor_create_surface(bar->compositor);
424 set_output_dirty(output); 475 assert(output->surface);
476 if (bar->visible) {
477 add_layer_surface(output);
478 }
425 } 479 }
426} 480}
427 481
@@ -517,14 +571,13 @@ static void set_bar_dirty(struct swaybar *bar) {
517 } 571 }
518} 572}
519 573
520bool bar_setup(struct swaybar *bar, 574bool bar_setup(struct swaybar *bar, const char *socket_path) {
521 const char *socket_path, const char *bar_id) {
522 bar_init(bar); 575 bar_init(bar);
523 init_event_loop(); 576 init_event_loop();
524 577
525 bar->ipc_socketfd = ipc_open_socket(socket_path); 578 bar->ipc_socketfd = ipc_open_socket(socket_path);
526 bar->ipc_event_socketfd = ipc_open_socket(socket_path); 579 bar->ipc_event_socketfd = ipc_open_socket(socket_path);
527 if (!ipc_initialize(bar, bar_id)) { 580 if (!ipc_initialize(bar)) {
528 return false; 581 return false;
529 } 582 }
530 if (bar->config->status_command) { 583 if (bar->config->status_command) {
@@ -565,8 +618,11 @@ bool bar_setup(struct swaybar *bar,
565 pointer->cursor_surface = wl_compositor_create_surface(bar->compositor); 618 pointer->cursor_surface = wl_compositor_create_surface(bar->compositor);
566 assert(pointer->cursor_surface); 619 assert(pointer->cursor_surface);
567 620
568 ipc_get_workspaces(bar); 621 if (bar->config->workspace_buttons) {
569 set_bar_dirty(bar); 622 if (ipc_get_workspaces(bar)) {
623 set_bar_dirty(bar);
624 }
625 }
570 return true; 626 return true;
571} 627}
572 628
@@ -625,4 +681,6 @@ void bar_teardown(struct swaybar *bar) {
625 if (bar->status) { 681 if (bar->status) {
626 status_line_free(bar->status); 682 status_line_free(bar->status);
627 } 683 }
684 free(bar->id);
685 free(bar->mode);
628} 686}
diff --git a/swaybar/config.c b/swaybar/config.c
index 09d40c24..eafb0b69 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -30,7 +30,8 @@ struct swaybar_config *init_config(void) {
30 config->pango_markup = false; 30 config->pango_markup = false;
31 config->position = parse_position("bottom"); 31 config->position = parse_position("bottom");
32 config->font = strdup("monospace 10"); 32 config->font = strdup("monospace 10");
33 config->mode = NULL; 33 config->mode = strdup("dock");
34 config->hidden_state = strdup("hide");
34 config->sep_symbol = NULL; 35 config->sep_symbol = NULL;
35 config->strip_workspace_numbers = false; 36 config->strip_workspace_numbers = false;
36 config->binding_mode_indicator = true; 37 config->binding_mode_indicator = true;
@@ -84,6 +85,7 @@ void free_config(struct swaybar_config *config) {
84 free(config->status_command); 85 free(config->status_command);
85 free(config->font); 86 free(config->font);
86 free(config->mode); 87 free(config->mode);
88 free(config->hidden_state);
87 free(config->sep_symbol); 89 free(config->sep_symbol);
88 for (int i = 0; i < config->bindings->length; i++) { 90 for (int i = 0; i < config->bindings->length; i++) {
89 struct swaybar_binding *binding = config->bindings->items[i]; 91 struct swaybar_binding *binding = config->bindings->items[i];
diff --git a/swaybar/ipc.c b/swaybar/ipc.c
index a67814c1..e1b30b52 100644
--- a/swaybar/ipc.c
+++ b/swaybar/ipc.c
@@ -152,12 +152,12 @@ static bool ipc_parse_config(
152 json_object_put(bar_config); 152 json_object_put(bar_config);
153 return false; 153 return false;
154 } 154 }
155 json_object *markup, *mode, *hidden_bar, *position, *status_command; 155 json_object *markup, *mode, *hidden_state, *position, *status_command;
156 json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; 156 json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers;
157 json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; 157 json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs;
158 json_object *bindings; 158 json_object *bindings;
159 json_object_object_get_ex(bar_config, "mode", &mode); 159 json_object_object_get_ex(bar_config, "mode", &mode);
160 json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); 160 json_object_object_get_ex(bar_config, "hidden_state", &hidden_state);
161 json_object_object_get_ex(bar_config, "position", &position); 161 json_object_object_get_ex(bar_config, "position", &position);
162 json_object_object_get_ex(bar_config, "status_command", &status_command); 162 json_object_object_get_ex(bar_config, "status_command", &status_command);
163 json_object_object_get_ex(bar_config, "font", &font); 163 json_object_object_get_ex(bar_config, "font", &font);
@@ -220,6 +220,14 @@ static bool ipc_parse_config(
220 list_add(config->bindings, binding); 220 list_add(config->bindings, binding);
221 } 221 }
222 } 222 }
223 if (hidden_state) {
224 free(config->hidden_state);
225 config->hidden_state = strdup(json_object_get_string(hidden_state));
226 }
227 if (mode) {
228 free(config->mode);
229 config->mode = strdup(json_object_get_string(mode));
230 }
223 231
224 struct config_output *output, *tmp; 232 struct config_output *output, *tmp;
225 wl_list_for_each_safe(output, tmp, &config->outputs, link) { 233 wl_list_for_each_safe(output, tmp, &config->outputs, link) {
@@ -254,7 +262,7 @@ static bool ipc_parse_config(
254 return true; 262 return true;
255} 263}
256 264
257void ipc_get_workspaces(struct swaybar *bar) { 265bool ipc_get_workspaces(struct swaybar *bar) {
258 struct swaybar_output *output; 266 struct swaybar_output *output;
259 wl_list_for_each(output, &bar->outputs, link) { 267 wl_list_for_each(output, &bar->outputs, link) {
260 free_workspaces(&output->workspaces); 268 free_workspaces(&output->workspaces);
@@ -266,8 +274,10 @@ void ipc_get_workspaces(struct swaybar *bar) {
266 json_object *results = json_tokener_parse(res); 274 json_object *results = json_tokener_parse(res);
267 if (!results) { 275 if (!results) {
268 free(res); 276 free(res);
269 return; 277 return false;
270 } 278 }
279
280 bar->visible_by_urgency = false;
271 size_t length = json_object_array_length(results); 281 size_t length = json_object_array_length(results);
272 json_object *ws_json; 282 json_object *ws_json;
273 json_object *num, *name, *visible, *focused, *out, *urgent; 283 json_object *num, *name, *visible, *focused, *out, *urgent;
@@ -294,12 +304,16 @@ void ipc_get_workspaces(struct swaybar *bar) {
294 output->focused = true; 304 output->focused = true;
295 } 305 }
296 ws->urgent = json_object_get_boolean(urgent); 306 ws->urgent = json_object_get_boolean(urgent);
307 if (ws->urgent) {
308 bar->visible_by_urgency = true;
309 }
297 wl_list_insert(&output->workspaces, &ws->link); 310 wl_list_insert(&output->workspaces, &ws->link);
298 } 311 }
299 } 312 }
300 } 313 }
301 json_object_put(results); 314 json_object_put(results);
302 free(res); 315 free(res);
316 return determine_bar_visibility(bar, false);
303} 317}
304 318
305static void ipc_get_outputs(struct swaybar *bar) { 319static void ipc_get_outputs(struct swaybar *bar) {
@@ -345,10 +359,10 @@ void ipc_execute_binding(struct swaybar *bar, struct swaybar_binding *bind) {
345 IPC_COMMAND, bind->command, &len)); 359 IPC_COMMAND, bind->command, &len));
346} 360}
347 361
348bool ipc_initialize(struct swaybar *bar, const char *bar_id) { 362bool ipc_initialize(struct swaybar *bar) {
349 uint32_t len = strlen(bar_id); 363 uint32_t len = strlen(bar->id);
350 char *res = ipc_single_command(bar->ipc_socketfd, 364 char *res = ipc_single_command(bar->ipc_socketfd,
351 IPC_GET_BAR_CONFIG, bar_id, &len); 365 IPC_GET_BAR_CONFIG, bar->id, &len);
352 if (!ipc_parse_config(bar->config, res)) { 366 if (!ipc_parse_config(bar->config, res)) {
353 free(res); 367 free(res);
354 return false; 368 return false;
@@ -356,56 +370,108 @@ bool ipc_initialize(struct swaybar *bar, const char *bar_id) {
356 free(res); 370 free(res);
357 ipc_get_outputs(bar); 371 ipc_get_outputs(bar);
358 372
359 const char *subscribe = "[ \"workspace\", \"mode\" ]"; 373 struct swaybar_config *config = bar->config;
360 len = strlen(subscribe); 374 char subscribe[128]; // suitably large buffer
375 len = snprintf(subscribe, 128,
376 "[ \"barconfig_update\" , \"bar_state_update\" %s %s ]",
377 config->binding_mode_indicator ? ", \"mode\"" : "",
378 config->workspace_buttons ? ", \"workspace\"" : "");
361 free(ipc_single_command(bar->ipc_event_socketfd, 379 free(ipc_single_command(bar->ipc_event_socketfd,
362 IPC_SUBSCRIBE, subscribe, &len)); 380 IPC_SUBSCRIBE, subscribe, &len));
363 return true; 381 return true;
364} 382}
365 383
384static bool handle_bar_state_update(struct swaybar *bar, json_object *event) {
385 json_object *json_id;
386 json_object_object_get_ex(event, "id", &json_id);
387 const char *id = json_object_get_string(json_id);
388 if (strcmp(id, bar->id) != 0) {
389 return false;
390 }
391
392 json_object *visible_by_modifier;
393 json_object_object_get_ex(event, "visible_by_modifier", &visible_by_modifier);
394 bar->visible_by_modifier = json_object_get_boolean(visible_by_modifier);
395 return determine_bar_visibility(bar, false);
396}
397
398static bool handle_barconfig_update(struct swaybar *bar,
399 json_object *json_config) {
400 json_object *json_id;
401 json_object_object_get_ex(json_config, "id", &json_id);
402 const char *id = json_object_get_string(json_id);
403 if (strcmp(id, bar->id) != 0) {
404 return false;
405 }
406
407 struct swaybar_config *config = bar->config;
408
409 json_object *json_state;
410 json_object_object_get_ex(json_config, "hidden_state", &json_state);
411 const char *new_state = json_object_get_string(json_state);
412 char *old_state = config->hidden_state;
413 if (strcmp(new_state, old_state) != 0) {
414 wlr_log(WLR_DEBUG, "Changing bar hidden state to %s", new_state);
415 free(old_state);
416 config->hidden_state = strdup(new_state);
417 return determine_bar_visibility(bar, false);
418 }
419
420 free(config->mode);
421 json_object *json_mode;
422 json_object_object_get_ex(json_config, "mode", &json_mode);
423 config->mode = strdup(json_object_get_string(json_mode));
424 wlr_log(WLR_DEBUG, "Changing bar mode to %s", config->mode);
425
426 return determine_bar_visibility(bar, true);
427}
428
366bool handle_ipc_readable(struct swaybar *bar) { 429bool handle_ipc_readable(struct swaybar *bar) {
367 struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); 430 struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd);
368 if (!resp) { 431 if (!resp) {
369 return false; 432 return false;
370 } 433 }
434
435 json_object *result = json_tokener_parse(resp->payload);
436 if (!result) {
437 wlr_log(WLR_ERROR, "failed to parse payload as json");
438 free_ipc_response(resp);
439 return false;
440 }
441
442 bool bar_is_dirty = true;
371 switch (resp->type) { 443 switch (resp->type) {
372 case IPC_EVENT_WORKSPACE: 444 case IPC_EVENT_WORKSPACE:
373 ipc_get_workspaces(bar); 445 bar_is_dirty = ipc_get_workspaces(bar);
374 break; 446 break;
375 case IPC_EVENT_MODE: { 447 case IPC_EVENT_MODE: {
376 json_object *result = json_tokener_parse(resp->payload);
377 if (!result) {
378 free_ipc_response(resp);
379 wlr_log(WLR_ERROR, "failed to parse payload as json");
380 return false;
381 }
382 json_object *json_change, *json_pango_markup; 448 json_object *json_change, *json_pango_markup;
383 if (json_object_object_get_ex(result, "change", &json_change)) { 449 if (json_object_object_get_ex(result, "change", &json_change)) {
384 const char *change = json_object_get_string(json_change); 450 const char *change = json_object_get_string(json_change);
385 free(bar->config->mode); 451 free(bar->mode);
386 if (strcmp(change, "default") == 0) { 452 bar->mode = strcmp(change, "default") != 0 ? strdup(change) : NULL;
387 bar->config->mode = NULL;
388 } else {
389 bar->config->mode = strdup(change);
390 }
391 } else { 453 } else {
392 wlr_log(WLR_ERROR, "failed to parse response"); 454 wlr_log(WLR_ERROR, "failed to parse response");
393 json_object_put(result); 455 bar_is_dirty = false;
394 free_ipc_response(resp); 456 break;
395 return false;
396 } 457 }
397 if (json_object_object_get_ex(result, 458 if (json_object_object_get_ex(result,
398 "pango_markup", &json_pango_markup)) { 459 "pango_markup", &json_pango_markup)) {
399 bar->config->mode_pango_markup = json_object_get_boolean( 460 bar->mode_pango_markup = json_object_get_boolean(json_pango_markup);
400 json_pango_markup);
401 } 461 }
402 json_object_put(result);
403 break; 462 break;
404 } 463 }
464 case IPC_EVENT_BARCONFIG_UPDATE:
465 bar_is_dirty = handle_barconfig_update(bar, result);
466 break;
467 case IPC_EVENT_BAR_STATE_UPDATE:
468 bar_is_dirty = handle_bar_state_update(bar, result);
469 break;
405 default: 470 default:
406 free_ipc_response(resp); 471 bar_is_dirty = false;
407 return false; 472 break;
408 } 473 }
474 json_object_put(result);
409 free_ipc_response(resp); 475 free_ipc_response(resp);
410 return true; 476 return bar_is_dirty;
411} 477}
diff --git a/swaybar/main.c b/swaybar/main.c
index db204f4a..2672abef 100644
--- a/swaybar/main.c
+++ b/swaybar/main.c
@@ -22,7 +22,6 @@ void sway_terminate(int code) {
22 22
23int main(int argc, char **argv) { 23int main(int argc, char **argv) {
24 char *socket_path = NULL; 24 char *socket_path = NULL;
25 char *bar_id = NULL;
26 bool debug = false; 25 bool debug = false;
27 26
28 static struct option long_options[] = { 27 static struct option long_options[] = {
@@ -59,7 +58,7 @@ int main(int argc, char **argv) {
59 socket_path = strdup(optarg); 58 socket_path = strdup(optarg);
60 break; 59 break;
61 case 'b': // Type 60 case 'b': // Type
62 bar_id = strdup(optarg); 61 swaybar.id = strdup(optarg);
63 break; 62 break;
64 case 'v': 63 case 'v':
65 fprintf(stdout, "swaybar version " SWAY_VERSION "\n"); 64 fprintf(stdout, "swaybar version " SWAY_VERSION "\n");
@@ -80,7 +79,7 @@ int main(int argc, char **argv) {
80 wlr_log_init(WLR_ERROR, NULL); 79 wlr_log_init(WLR_ERROR, NULL);
81 } 80 }
82 81
83 if (!bar_id) { 82 if (!swaybar.id) {
84 wlr_log(WLR_ERROR, "No bar_id passed. " 83 wlr_log(WLR_ERROR, "No bar_id passed. "
85 "Provide --bar_id or let sway start swaybar"); 84 "Provide --bar_id or let sway start swaybar");
86 return 1; 85 return 1;
@@ -96,13 +95,12 @@ int main(int argc, char **argv) {
96 95
97 signal(SIGTERM, sig_handler); 96 signal(SIGTERM, sig_handler);
98 97
99 if (!bar_setup(&swaybar, socket_path, bar_id)) { 98 if (!bar_setup(&swaybar, socket_path)) {
100 free(socket_path); 99 free(socket_path);
101 return 1; 100 return 1;
102 } 101 }
103 102
104 free(socket_path); 103 free(socket_path);
105 free(bar_id);
106 104
107 bar_run(&swaybar); 105 bar_run(&swaybar);
108 bar_teardown(&swaybar); 106 bar_teardown(&swaybar);
diff --git a/swaybar/render.c b/swaybar/render.c
index dc31a5ea..097eb462 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -296,11 +296,15 @@ static uint32_t render_status_line(cairo_t *cairo,
296 296
297static uint32_t render_binding_mode_indicator(cairo_t *cairo, 297static uint32_t render_binding_mode_indicator(cairo_t *cairo,
298 struct swaybar_output *output, double x) { 298 struct swaybar_output *output, double x) {
299 const char *mode = output->bar->mode;
300 if (!mode) {
301 return 0;
302 }
303
299 struct swaybar_config *config = output->bar->config; 304 struct swaybar_config *config = output->bar->config;
300 const char *mode = config->mode;
301 int text_width, text_height; 305 int text_width, text_height;
302 get_text_size(cairo, config->font, &text_width, &text_height, NULL, 306 get_text_size(cairo, config->font, &text_width, &text_height, NULL,
303 output->scale, config->mode_pango_markup, 307 output->scale, output->bar->mode_pango_markup,
304 "%s", mode); 308 "%s", mode);
305 309
306 int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; 310 int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale;
@@ -333,8 +337,8 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo,
333 double text_y = height / 2.0 - text_height / 2.0; 337 double text_y = height / 2.0 - text_height / 2.0;
334 cairo_set_source_u32(cairo, config->colors.binding_mode.text); 338 cairo_set_source_u32(cairo, config->colors.binding_mode.text);
335 cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); 339 cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y));
336 pango_printf(cairo, config->font, output->scale, config->mode_pango_markup, 340 pango_printf(cairo, config->font, output->scale,
337 "%s", mode); 341 output->bar->mode_pango_markup, "%s", mode);
338 return output->height; 342 return output->height;
339} 343}
340 344
@@ -465,7 +469,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) {
465 max_height = h > max_height ? h : max_height; 469 max_height = h > max_height ? h : max_height;
466 } 470 }
467 } 471 }
468 if (config->binding_mode_indicator && config->mode) { 472 if (config->binding_mode_indicator) {
469 uint32_t h = render_binding_mode_indicator(cairo, output, x); 473 uint32_t h = render_binding_mode_indicator(cairo, output, x);
470 max_height = h > max_height ? h : max_height; 474 max_height = h > max_height ? h : max_height;
471 } 475 }
@@ -490,16 +494,12 @@ static const struct wl_callback_listener output_frame_listener = {
490 494
491void render_frame(struct swaybar_output *output) { 495void render_frame(struct swaybar_output *output) {
492 assert(output->surface != NULL); 496 assert(output->surface != NULL);
493 497 if (!output->layer_surface) {
494 struct swaybar_hotspot *hotspot, *tmp; 498 return;
495 wl_list_for_each_safe(hotspot, tmp, &output->hotspots, link) {
496 if (hotspot->destroy) {
497 hotspot->destroy(hotspot->data);
498 }
499 wl_list_remove(&hotspot->link);
500 free(hotspot);
501 } 499 }
502 500
501 free_hotspots(&output->hotspots);
502
503 cairo_surface_t *recorder = cairo_recording_surface_create( 503 cairo_surface_t *recorder = cairo_recording_surface_create(
504 CAIRO_CONTENT_COLOR_ALPHA, NULL); 504 CAIRO_CONTENT_COLOR_ALPHA, NULL);
505 cairo_t *cairo = cairo_create(recorder); 505 cairo_t *cairo = cairo_create(recorder);
@@ -519,10 +519,12 @@ void render_frame(struct swaybar_output *output) {
519 if (config_height >= 0 && height < (uint32_t)config_height) { 519 if (config_height >= 0 && height < (uint32_t)config_height) {
520 height = config_height; 520 height = config_height;
521 } 521 }
522 if (height != output->height) { 522 if (height != output->height || output->width == 0) {
523 // Reconfigure surface 523 // Reconfigure surface
524 zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); 524 zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height);
525 zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); 525 if (strcmp(output->bar->config->mode, "dock") == 0) {
526 zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height);
527 }
526 // TODO: this could infinite loop if the compositor assigns us a 528 // TODO: this could infinite loop if the compositor assigns us a
527 // different height than what we asked for 529 // different height than what we asked for
528 wl_surface_commit(output->surface); 530 wl_surface_commit(output->surface);
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
index ed6dc7c8..000609ce 100644
--- a/swaybar/status_line.c
+++ b/swaybar/status_line.c
@@ -83,6 +83,17 @@ bool status_handle_readable(struct status_line *status) {
83 return true; 83 return true;
84 } 84 }
85 } 85 }
86
87 json_object *signal;
88 if (json_object_object_get_ex(header, "stop_signal", &signal)) {
89 status->stop_signal = json_object_get_int(signal);
90 wlr_log(WLR_DEBUG, "Setting stop signal to %d", status->stop_signal);
91 }
92 if (json_object_object_get_ex(header, "cont_signal", &signal)) {
93 status->cont_signal = json_object_get_int(signal);
94 wlr_log(WLR_DEBUG, "Setting cont signal to %d", status->cont_signal);
95 }
96
86 json_object_put(header); 97 json_object_put(header);
87 98
88 wl_list_init(&status->blocks); 99 wl_list_init(&status->blocks);
@@ -121,6 +132,9 @@ bool status_handle_readable(struct status_line *status) {
121 132
122struct status_line *status_line_init(char *cmd) { 133struct status_line *status_line_init(char *cmd) {
123 struct status_line *status = calloc(1, sizeof(struct status_line)); 134 struct status_line *status = calloc(1, sizeof(struct status_line));
135 status->stop_signal = SIGSTOP;
136 status->cont_signal = SIGCONT;
137
124 status->buffer_size = 8192; 138 status->buffer_size = 8192;
125 status->buffer = malloc(status->buffer_size); 139 status->buffer = malloc(status->buffer_size);
126 140