diff options
-rw-r--r-- | include/bar/bar.h | 11 | ||||
-rw-r--r-- | include/bar/config.h | 4 | ||||
-rw-r--r-- | include/bar/ipc.h | 2 | ||||
-rw-r--r-- | include/config.h | 8 | ||||
-rw-r--r-- | include/container.h | 4 | ||||
-rw-r--r-- | sway/commands.c | 9 | ||||
-rw-r--r-- | sway/config.c | 89 | ||||
-rw-r--r-- | sway/container.c | 5 | ||||
-rw-r--r-- | sway/ipc-server.c | 11 | ||||
-rw-r--r-- | sway/main.c | 4 | ||||
-rw-r--r-- | swaybar/bar.c | 122 | ||||
-rw-r--r-- | swaybar/config.c | 2 | ||||
-rw-r--r-- | swaybar/ipc.c | 119 | ||||
-rw-r--r-- | swaybar/main.c | 10 |
14 files changed, 256 insertions, 144 deletions
diff --git a/include/bar/bar.h b/include/bar/bar.h index 89496da6..c20efc55 100644 --- a/include/bar/bar.h +++ b/include/bar/bar.h | |||
@@ -8,8 +8,7 @@ | |||
8 | struct bar { | 8 | struct bar { |
9 | struct config *config; | 9 | struct config *config; |
10 | struct status_line *status; | 10 | struct status_line *status; |
11 | struct output *output; | 11 | list_t *outputs; |
12 | /* list_t *outputs; */ | ||
13 | 12 | ||
14 | int ipc_event_socketfd; | 13 | int ipc_event_socketfd; |
15 | int ipc_socketfd; | 14 | int ipc_socketfd; |
@@ -22,6 +21,7 @@ struct output { | |||
22 | struct registry *registry; | 21 | struct registry *registry; |
23 | list_t *workspaces; | 22 | list_t *workspaces; |
24 | char *name; | 23 | char *name; |
24 | int idx; | ||
25 | }; | 25 | }; |
26 | 26 | ||
27 | struct workspace { | 27 | struct workspace { |
@@ -35,7 +35,12 @@ struct workspace { | |||
35 | /** | 35 | /** |
36 | * Setup bar. | 36 | * Setup bar. |
37 | */ | 37 | */ |
38 | void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id, int desired_output); | 38 | void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id); |
39 | |||
40 | /** | ||
41 | * Create new output struct from name. | ||
42 | */ | ||
43 | struct output *new_output(const char *name); | ||
39 | 44 | ||
40 | /** | 45 | /** |
41 | * Bar mainloop. | 46 | * Bar mainloop. |
diff --git a/include/bar/config.h b/include/bar/config.h index 508b9c42..fc938c38 100644 --- a/include/bar/config.h +++ b/include/bar/config.h | |||
@@ -4,6 +4,8 @@ | |||
4 | #include <stdint.h> | 4 | #include <stdint.h> |
5 | #include <stdbool.h> | 5 | #include <stdbool.h> |
6 | 6 | ||
7 | #include "list.h" | ||
8 | |||
7 | /** | 9 | /** |
8 | * Colors for a box with background, border and text colors. | 10 | * Colors for a box with background, border and text colors. |
9 | */ | 11 | */ |
@@ -25,6 +27,8 @@ struct config { | |||
25 | bool strip_workspace_numbers; | 27 | bool strip_workspace_numbers; |
26 | bool binding_mode_indicator; | 28 | bool binding_mode_indicator; |
27 | bool workspace_buttons; | 29 | bool workspace_buttons; |
30 | bool all_outputs; | ||
31 | list_t *outputs; | ||
28 | 32 | ||
29 | int height; | 33 | int height; |
30 | 34 | ||
diff --git a/include/bar/ipc.h b/include/bar/ipc.h index c3f661f8..741c067b 100644 --- a/include/bar/ipc.h +++ b/include/bar/ipc.h | |||
@@ -6,7 +6,7 @@ | |||
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 | */ |
9 | void ipc_bar_init(struct bar *bar, int outputi, const char *bar_id); | 9 | void ipc_bar_init(struct bar *bar, const char *bar_id); |
10 | 10 | ||
11 | /** | 11 | /** |
12 | * Handle ipc event from sway. | 12 | * Handle ipc event from sway. |
diff --git a/include/config.h b/include/config.h index 655d0a9c..d77872ee 100644 --- a/include/config.h +++ b/include/config.h | |||
@@ -125,6 +125,7 @@ struct bar_config { | |||
125 | bool strip_workspace_numbers; | 125 | bool strip_workspace_numbers; |
126 | bool binding_mode_indicator; | 126 | bool binding_mode_indicator; |
127 | bool verbose; | 127 | bool verbose; |
128 | pid_t pid; | ||
128 | struct { | 129 | struct { |
129 | char background[10]; | 130 | char background[10]; |
130 | char statusline[10]; | 131 | char statusline[10]; |
@@ -192,6 +193,10 @@ bool load_config(const char *file); | |||
192 | */ | 193 | */ |
193 | bool read_config(FILE *file, bool is_active); | 194 | bool read_config(FILE *file, bool is_active); |
194 | /** | 195 | /** |
196 | * Free config struct | ||
197 | */ | ||
198 | void free_config(struct sway_config *config); | ||
199 | /** | ||
195 | * Does variable replacement for a string based on the config's currently loaded variables. | 200 | * Does variable replacement for a string based on the config's currently loaded variables. |
196 | */ | 201 | */ |
197 | char *do_var_replacement(char *str); | 202 | char *do_var_replacement(char *str); |
@@ -226,8 +231,7 @@ int sway_mouse_binding_cmp_qsort(const void *a, const void *b); | |||
226 | int sway_mouse_binding_cmp_buttons(const void *a, const void *b); | 231 | int sway_mouse_binding_cmp_buttons(const void *a, const void *b); |
227 | void free_sway_mouse_binding(struct sway_mouse_binding *smb); | 232 | void free_sway_mouse_binding(struct sway_mouse_binding *smb); |
228 | 233 | ||
229 | void load_swaybars(swayc_t *output, int output_idx); | 234 | void load_swaybars(); |
230 | void terminate_swaybars(list_t *pids); | ||
231 | void terminate_swaybg(pid_t pid); | 235 | void terminate_swaybg(pid_t pid); |
232 | 236 | ||
233 | /** | 237 | /** |
diff --git a/include/container.h b/include/container.h index d5126e74..a96beab9 100644 --- a/include/container.h +++ b/include/container.h | |||
@@ -82,9 +82,7 @@ struct sway_container { | |||
82 | char *class; | 82 | char *class; |
83 | char *app_id; | 83 | char *app_id; |
84 | 84 | ||
85 | // Used by output containers to keep track of swaybar/swaybg child | 85 | // Used by output containers to keep track of swaybg child processes. |
86 | // processes. | ||
87 | list_t *bar_pids; | ||
88 | pid_t bg_pid; | 86 | pid_t bg_pid; |
89 | 87 | ||
90 | int gaps; | 88 | int gaps; |
diff --git a/sway/commands.c b/sway/commands.c index c4b7f6ab..3b8556ca 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -1526,14 +1526,7 @@ static struct cmd_results *cmd_reload(int argc, char **argv) { | |||
1526 | } | 1526 | } |
1527 | if (!load_config(NULL)) return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); | 1527 | if (!load_config(NULL)) return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); |
1528 | 1528 | ||
1529 | int i; | 1529 | load_swaybars(); |
1530 | swayc_t *cont = NULL; | ||
1531 | for (i = 0; i < root_container.children->length; ++i) { | ||
1532 | cont = root_container.children->items[i]; | ||
1533 | if (cont->type == C_OUTPUT) { | ||
1534 | load_swaybars(cont, i); | ||
1535 | } | ||
1536 | } | ||
1537 | 1530 | ||
1538 | arrange_windows(&root_container, -1, -1); | 1531 | arrange_windows(&root_container, -1, -1); |
1539 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | 1532 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); |
diff --git a/sway/config.c b/sway/config.c index 65dba365..296e164c 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -23,6 +23,8 @@ | |||
23 | 23 | ||
24 | struct sway_config *config = NULL; | 24 | struct sway_config *config = NULL; |
25 | 25 | ||
26 | static void terminate_swaybar(pid_t pid); | ||
27 | |||
26 | static void free_variable(struct sway_variable *var) { | 28 | static void free_variable(struct sway_variable *var) { |
27 | free(var->name); | 29 | free(var->name); |
28 | free(var->value); | 30 | free(var->value); |
@@ -60,6 +62,11 @@ static void free_bar(struct bar_config *bar) { | |||
60 | if (bar->outputs) { | 62 | if (bar->outputs) { |
61 | free_flat_list(bar->outputs); | 63 | free_flat_list(bar->outputs); |
62 | } | 64 | } |
65 | |||
66 | if (bar->pid != 0) { | ||
67 | terminate_swaybar(bar->pid); | ||
68 | } | ||
69 | |||
63 | free(bar); | 70 | free(bar); |
64 | } | 71 | } |
65 | 72 | ||
@@ -79,7 +86,7 @@ static void free_workspace_output(struct workspace_output *wo) { | |||
79 | free(wo); | 86 | free(wo); |
80 | } | 87 | } |
81 | 88 | ||
82 | static void free_config(struct sway_config *config) { | 89 | void free_config(struct sway_config *config) { |
83 | int i; | 90 | int i; |
84 | for (i = 0; i < config->symbols->length; ++i) { | 91 | for (i = 0; i < config->symbols->length; ++i) { |
85 | free_variable(config->symbols->items[i]); | 92 | free_variable(config->symbols->items[i]); |
@@ -471,32 +478,23 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { | |||
471 | } | 478 | } |
472 | } | 479 | } |
473 | 480 | ||
474 | static void invoke_swaybar(swayc_t *output, struct bar_config *bar, int output_i) { | 481 | static void invoke_swaybar(struct bar_config *bar) { |
475 | sway_log(L_DEBUG, "Invoking swaybar for output %s[%d] and bar %s", output->name, output_i, bar->id); | 482 | bar->pid = fork(); |
476 | 483 | if (bar->pid == 0) { | |
477 | size_t bufsize = 4; | ||
478 | char output_id[bufsize]; | ||
479 | snprintf(output_id, bufsize, "%d", output_i); | ||
480 | output_id[bufsize-1] = 0; | ||
481 | |||
482 | pid_t *pid = malloc(sizeof(pid_t)); | ||
483 | *pid = fork(); | ||
484 | if (*pid == 0) { | ||
485 | if (!bar->swaybar_command) { | 484 | if (!bar->swaybar_command) { |
486 | char *const cmd[] = { | 485 | char *const cmd[] = { |
487 | "swaybar", | 486 | "swaybar", |
488 | "-b", | 487 | "-b", |
489 | bar->id, | 488 | bar->id, |
490 | output_id, | ||
491 | NULL, | 489 | NULL, |
492 | }; | 490 | }; |
493 | 491 | ||
494 | execvp(cmd[0], cmd); | 492 | execvp(cmd[0], cmd); |
495 | } else { | 493 | } else { |
496 | // run custom swaybar | 494 | // run custom swaybar |
497 | int len = strlen(bar->swaybar_command) + strlen(bar->id) + strlen(output_id) + 6; | 495 | int len = strlen(bar->swaybar_command) + strlen(bar->id) + 5; |
498 | char *command = malloc(len * sizeof(char)); | 496 | char *command = malloc(len * sizeof(char)); |
499 | snprintf(command, len, "%s -b %s %s", bar->swaybar_command, bar->id, output_id); | 497 | snprintf(command, len, "%s -b %s", bar->swaybar_command, bar->id); |
500 | 498 | ||
501 | char *const cmd[] = { | 499 | char *const cmd[] = { |
502 | "sh", | 500 | "sh", |
@@ -509,30 +507,15 @@ static void invoke_swaybar(swayc_t *output, struct bar_config *bar, int output_i | |||
509 | free(command); | 507 | free(command); |
510 | } | 508 | } |
511 | } | 509 | } |
512 | |||
513 | // add swaybar pid to output | ||
514 | list_add(output->bar_pids, pid); | ||
515 | } | 510 | } |
516 | 511 | ||
517 | void terminate_swaybars(list_t *pids) { | 512 | static void terminate_swaybar(pid_t pid) { |
518 | int i, ret; | 513 | int ret = kill(pid, SIGTERM); |
519 | pid_t *pid; | 514 | if (ret != 0) { |
520 | for (i = 0; i < pids->length; ++i) { | 515 | sway_log(L_ERROR, "Unable to terminate swaybar [pid: %d]", pid); |
521 | pid = pids->items[i]; | 516 | } else { |
522 | ret = kill(*pid, SIGTERM); | 517 | int status; |
523 | if (ret != 0) { | 518 | waitpid(pid, &status, 0); |
524 | sway_log(L_ERROR, "Unable to terminate swaybar [pid: %d]", *pid); | ||
525 | } else { | ||
526 | int status; | ||
527 | waitpid(*pid, &status, 0); | ||
528 | } | ||
529 | } | ||
530 | |||
531 | // empty pids list | ||
532 | for (i = 0; i < pids->length; ++i) { | ||
533 | pid = pids->items[i]; | ||
534 | list_del(pids, i); | ||
535 | free(pid); | ||
536 | } | 519 | } |
537 | } | 520 | } |
538 | 521 | ||
@@ -546,7 +529,20 @@ void terminate_swaybg(pid_t pid) { | |||
546 | } | 529 | } |
547 | } | 530 | } |
548 | 531 | ||
549 | void load_swaybars(swayc_t *output, int output_idx) { | 532 | static bool active_output(const char *name) { |
533 | int i; | ||
534 | swayc_t *cont = NULL; | ||
535 | for (i = 0; i < root_container.children->length; ++i) { | ||
536 | cont = root_container.children->items[i]; | ||
537 | if (cont->type == C_OUTPUT && strcasecmp(name, cont->name) == 0) { | ||
538 | return true; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | return false; | ||
543 | } | ||
544 | |||
545 | void load_swaybars() { | ||
550 | // Check for bars | 546 | // Check for bars |
551 | list_t *bars = create_list(); | 547 | list_t *bars = create_list(); |
552 | struct bar_config *bar = NULL; | 548 | struct bar_config *bar = NULL; |
@@ -558,7 +554,7 @@ void load_swaybars(swayc_t *output, int output_idx) { | |||
558 | int j; | 554 | int j; |
559 | for (j = 0; j < bar->outputs->length; ++j) { | 555 | for (j = 0; j < bar->outputs->length; ++j) { |
560 | char *o = bar->outputs->items[j]; | 556 | char *o = bar->outputs->items[j]; |
561 | if (!strcmp(o, "*") || !strcasecmp(o, output->name)) { | 557 | if (!strcmp(o, "*") || active_output(o)) { |
562 | apply = true; | 558 | apply = true; |
563 | break; | 559 | break; |
564 | } | 560 | } |
@@ -571,13 +567,13 @@ void load_swaybars(swayc_t *output, int output_idx) { | |||
571 | } | 567 | } |
572 | } | 568 | } |
573 | 569 | ||
574 | // terminate swaybar processes previously spawned for this | ||
575 | // output. | ||
576 | terminate_swaybars(output->bar_pids); | ||
577 | |||
578 | for (i = 0; i < bars->length; ++i) { | 570 | for (i = 0; i < bars->length; ++i) { |
579 | bar = bars->items[i]; | 571 | bar = bars->items[i]; |
580 | invoke_swaybar(output, bar, output_idx); | 572 | if (bar->pid != 0) { |
573 | terminate_swaybar(bar->pid); | ||
574 | } | ||
575 | sway_log(L_DEBUG, "Invoking swaybar for bar id '%s'", bar->id); | ||
576 | invoke_swaybar(bar); | ||
581 | } | 577 | } |
582 | 578 | ||
583 | list_free(bars); | 579 | list_free(bars); |
@@ -700,8 +696,8 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { | |||
700 | } | 696 | } |
701 | } | 697 | } |
702 | 698 | ||
703 | // load swaybars for output | 699 | // reload swaybars |
704 | load_swaybars(output, output_i); | 700 | load_swaybars(); |
705 | } | 701 | } |
706 | 702 | ||
707 | char *do_var_replacement(char *str) { | 703 | char *do_var_replacement(char *str) { |
@@ -889,6 +885,7 @@ struct bar_config *default_bar_config(void) { | |||
889 | bar->strip_workspace_numbers = false; | 885 | bar->strip_workspace_numbers = false; |
890 | bar->binding_mode_indicator = true; | 886 | bar->binding_mode_indicator = true; |
891 | bar->tray_padding = 2; | 887 | bar->tray_padding = 2; |
888 | bar->pid = 0; | ||
892 | // set default colors | 889 | // set default colors |
893 | strcpy(bar->colors.background, "#000000ff"); | 890 | strcpy(bar->colors.background, "#000000ff"); |
894 | strcpy(bar->colors.statusline, "#ffffffff"); | 891 | strcpy(bar->colors.statusline, "#ffffffff"); |
diff --git a/sway/container.c b/sway/container.c index 746890c9..2db7b218 100644 --- a/sway/container.c +++ b/sway/container.c | |||
@@ -61,10 +61,6 @@ static void free_swayc(swayc_t *cont) { | |||
61 | if (cont->app_id) { | 61 | if (cont->app_id) { |
62 | free(cont->app_id); | 62 | free(cont->app_id); |
63 | } | 63 | } |
64 | if (cont->bar_pids) { | ||
65 | terminate_swaybars(cont->bar_pids); | ||
66 | free_flat_list(cont->bar_pids); | ||
67 | } | ||
68 | if (cont->bg_pid != 0) { | 64 | if (cont->bg_pid != 0) { |
69 | terminate_swaybg(cont->bg_pid); | 65 | terminate_swaybg(cont->bg_pid); |
70 | } | 66 | } |
@@ -123,7 +119,6 @@ swayc_t *new_output(wlc_handle handle) { | |||
123 | output->width = size->w; | 119 | output->width = size->w; |
124 | output->height = size->h; | 120 | output->height = size->h; |
125 | output->unmanaged = create_list(); | 121 | output->unmanaged = create_list(); |
126 | output->bar_pids = create_list(); | ||
127 | output->bg_pid = 0; | 122 | output->bg_pid = 0; |
128 | 123 | ||
129 | apply_output_config(oc, output); | 124 | apply_output_config(oc, output); |
diff --git a/sway/ipc-server.c b/sway/ipc-server.c index a63026c6..9ea034d1 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c | |||
@@ -628,6 +628,17 @@ json_object *ipc_json_describe_bar_config(struct bar_config *bar) { | |||
628 | 628 | ||
629 | json_object_object_add(json, "colors", colors); | 629 | json_object_object_add(json, "colors", colors); |
630 | 630 | ||
631 | // Add outputs if defined | ||
632 | if (bar->outputs && bar->outputs->length > 0) { | ||
633 | json_object *outputs = json_object_new_array(); | ||
634 | int i; | ||
635 | for (i = 0; i < bar->outputs->length; ++i) { | ||
636 | const char *name = bar->outputs->items[i]; | ||
637 | json_object_array_add(outputs, json_object_new_string(name)); | ||
638 | } | ||
639 | json_object_object_add(json, "outputs", outputs); | ||
640 | } | ||
641 | |||
631 | return json; | 642 | return json; |
632 | } | 643 | } |
633 | 644 | ||
diff --git a/sway/main.c b/sway/main.c index 7ea392b6..7c712281 100644 --- a/sway/main.c +++ b/sway/main.c | |||
@@ -228,6 +228,10 @@ int main(int argc, char **argv) { | |||
228 | 228 | ||
229 | ipc_terminate(); | 229 | ipc_terminate(); |
230 | 230 | ||
231 | if (config) { | ||
232 | free_config(config); | ||
233 | } | ||
234 | |||
231 | return exit_value; | 235 | return exit_value; |
232 | } | 236 | } |
233 | 237 | ||
diff --git a/swaybar/bar.c b/swaybar/bar.c index d80c9af3..b6329123 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c | |||
@@ -1,9 +1,10 @@ | |||
1 | #include <stdlib.h> | 1 | #include <stdlib.h> |
2 | #include <unistd.h> | 2 | #include <unistd.h> |
3 | #include <string.h> | ||
3 | #include <fcntl.h> | 4 | #include <fcntl.h> |
4 | #include <errno.h> | 5 | #include <errno.h> |
5 | #include <sys/types.h> | ||
6 | #include <sys/wait.h> | 6 | #include <sys/wait.h> |
7 | #include <poll.h> | ||
7 | 8 | ||
8 | #include "ipc-client.h" | 9 | #include "ipc-client.h" |
9 | #include "list.h" | 10 | #include "list.h" |
@@ -17,11 +18,7 @@ | |||
17 | static void bar_init(struct bar *bar) { | 18 | static void bar_init(struct bar *bar) { |
18 | bar->config = init_config(); | 19 | bar->config = init_config(); |
19 | bar->status = init_status_line(); | 20 | bar->status = init_status_line(); |
20 | bar->output = malloc(sizeof(struct output)); | 21 | bar->outputs = create_list(); |
21 | bar->output->window = NULL; | ||
22 | bar->output->registry = NULL; | ||
23 | bar->output->workspaces = create_list(); | ||
24 | bar->output->name = NULL; | ||
25 | } | 22 | } |
26 | 23 | ||
27 | static void spawn_status_cmd_proc(struct bar *bar) { | 24 | static void spawn_status_cmd_proc(struct bar *bar) { |
@@ -49,78 +46,109 @@ static void spawn_status_cmd_proc(struct bar *bar) { | |||
49 | } | 46 | } |
50 | } | 47 | } |
51 | 48 | ||
49 | struct output *new_output(const char *name) { | ||
50 | struct output *output = malloc(sizeof(struct output)); | ||
51 | output->name = strdup(name); | ||
52 | output->window = NULL; | ||
53 | output->registry = NULL; | ||
54 | output->workspaces = create_list(); | ||
55 | return output; | ||
56 | } | ||
52 | 57 | ||
53 | void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id, int desired_output) { | 58 | void bar_setup(struct bar *bar, const char *socket_path, const char *bar_id) { |
54 | /* initialize bar with default values */ | 59 | /* initialize bar with default values */ |
55 | bar_init(bar); | 60 | bar_init(bar); |
56 | 61 | ||
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 */ | 62 | /* connect to sway ipc */ |
64 | bar->ipc_socketfd = ipc_open_socket(socket_path); | 63 | bar->ipc_socketfd = ipc_open_socket(socket_path); |
65 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); | 64 | bar->ipc_event_socketfd = ipc_open_socket(socket_path); |
66 | 65 | ||
67 | ipc_bar_init(bar, desired_output, bar_id); | 66 | ipc_bar_init(bar, bar_id); |
68 | 67 | ||
69 | struct output_state *output = bar->output->registry->outputs->items[desired_output]; | 68 | int i; |
69 | for (i = 0; i < bar->outputs->length; ++i) { | ||
70 | struct output *bar_output = bar->outputs->items[i]; | ||
70 | 71 | ||
71 | bar->output->window = window_setup(bar->output->registry, output->width, 30, false); | 72 | bar_output->registry = registry_poll(); |
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 | 73 | ||
78 | /* set font */ | 74 | if (!bar_output->registry->desktop_shell) { |
79 | bar->output->window->font = bar->config->font; | 75 | sway_abort("swaybar requires the compositor to support the desktop-shell extension."); |
76 | } | ||
80 | 77 | ||
81 | /* set window height */ | 78 | struct output_state *output = bar_output->registry->outputs->items[bar_output->idx]; |
82 | set_window_height(bar->output->window, bar->config->height); | ||
83 | 79 | ||
80 | bar_output->window = window_setup(bar_output->registry, output->width, 30, false); | ||
81 | if (!bar_output->window) { | ||
82 | sway_abort("Failed to create window."); | ||
83 | } | ||
84 | desktop_shell_set_panel(bar_output->registry->desktop_shell, output->output, bar_output->window->surface); | ||
85 | desktop_shell_set_panel_position(bar_output->registry->desktop_shell, bar->config->position); | ||
86 | |||
87 | /* set font */ | ||
88 | bar_output->window->font = bar->config->font; | ||
89 | |||
90 | /* set window height */ | ||
91 | set_window_height(bar_output->window, bar->config->height); | ||
92 | } | ||
84 | /* spawn status command */ | 93 | /* spawn status command */ |
85 | spawn_status_cmd_proc(bar); | 94 | spawn_status_cmd_proc(bar); |
86 | } | 95 | } |
87 | 96 | ||
88 | void bar_run(struct bar *bar) { | 97 | void bar_run(struct bar *bar) { |
89 | fd_set readfds; | 98 | int pfds = bar->outputs->length + 2; |
90 | int activity; | 99 | struct pollfd *pfd = malloc(pfds * sizeof(struct pollfd)); |
91 | bool dirty = true; | 100 | bool dirty = true; |
92 | 101 | ||
102 | pfd[0].fd = bar->ipc_event_socketfd; | ||
103 | pfd[0].events = POLLIN; | ||
104 | pfd[1].fd = bar->status_read_fd; | ||
105 | pfd[1].events = POLLIN; | ||
106 | |||
107 | int i; | ||
108 | for (i = 0; i < bar->outputs->length; ++i) { | ||
109 | struct output *output = bar->outputs->items[i]; | ||
110 | pfd[i+2].fd = wl_display_get_fd(output->registry->display); | ||
111 | pfd[i+2].events = POLLIN; | ||
112 | } | ||
113 | |||
93 | while (1) { | 114 | while (1) { |
94 | if (dirty) { | 115 | if (dirty) { |
95 | struct output *output = bar->output; | 116 | int i; |
96 | if (window_prerender(output->window) && output->window->cairo) { | 117 | for (i = 0; i < bar->outputs->length; ++i) { |
97 | render(output, bar->config, bar->status); | 118 | struct output *output = bar->outputs->items[i]; |
98 | window_render(output->window); | 119 | if (window_prerender(output->window) && output->window->cairo) { |
99 | if (wl_display_dispatch(output->registry->display) == -1) { | 120 | render(output, bar->config, bar->status); |
100 | break; | 121 | window_render(output->window); |
122 | wl_display_flush(output->registry->display); | ||
101 | } | 123 | } |
102 | } | 124 | } |
103 | } | 125 | } |
104 | 126 | ||
105 | dirty = false; | 127 | dirty = false; |
106 | FD_ZERO(&readfds); | ||
107 | FD_SET(bar->ipc_event_socketfd, &readfds); | ||
108 | FD_SET(bar->status_read_fd, &readfds); | ||
109 | 128 | ||
110 | activity = select(FD_SETSIZE, &readfds, NULL, NULL, NULL); | 129 | poll(pfd, pfds, -1); |
111 | if (activity < 0) { | ||
112 | sway_log(L_ERROR, "polling failed: %d", errno); | ||
113 | } | ||
114 | 130 | ||
115 | if (FD_ISSET(bar->ipc_event_socketfd, &readfds)) { | 131 | if (pfd[0].revents & POLLIN) { |
116 | sway_log(L_DEBUG, "Got IPC event."); | 132 | sway_log(L_DEBUG, "Got IPC event."); |
117 | dirty = handle_ipc_event(bar); | 133 | dirty = handle_ipc_event(bar); |
118 | } | 134 | } |
119 | 135 | ||
120 | if (bar->config->status_command && FD_ISSET(bar->status_read_fd, &readfds)) { | 136 | if (bar->config->status_command && pfd[1].revents & POLLIN) { |
121 | sway_log(L_DEBUG, "Got update from status command."); | 137 | sway_log(L_DEBUG, "Got update from status command."); |
122 | dirty = handle_status_line(bar); | 138 | dirty = handle_status_line(bar); |
123 | } | 139 | } |
140 | |||
141 | // dispatch wl_display events | ||
142 | for (i = 0; i < bar->outputs->length; ++i) { | ||
143 | struct output *output = bar->outputs->items[i]; | ||
144 | if (pfd[i+2].revents & POLLIN) { | ||
145 | if (wl_display_dispatch(output->registry->display) == -1) { | ||
146 | sway_log(L_ERROR, "failed to dispatch wl: %d", errno); | ||
147 | } | ||
148 | } else { | ||
149 | wl_display_dispatch_pending(output->registry->display); | ||
150 | } | ||
151 | } | ||
124 | } | 152 | } |
125 | } | 153 | } |
126 | 154 | ||
@@ -149,6 +177,14 @@ static void free_output(struct output *output) { | |||
149 | free(output); | 177 | free(output); |
150 | } | 178 | } |
151 | 179 | ||
180 | static void free_outputs(list_t *outputs) { | ||
181 | int i; | ||
182 | for (i = 0; i < outputs->length; ++i) { | ||
183 | free_output(outputs->items[i]); | ||
184 | } | ||
185 | list_free(outputs); | ||
186 | } | ||
187 | |||
152 | static void terminate_status_command(pid_t pid) { | 188 | static void terminate_status_command(pid_t pid) { |
153 | if (pid) { | 189 | if (pid) { |
154 | // terminate status_command process | 190 | // terminate status_command process |
@@ -164,7 +200,7 @@ static void terminate_status_command(pid_t pid) { | |||
164 | 200 | ||
165 | void bar_teardown(struct bar *bar) { | 201 | void bar_teardown(struct bar *bar) { |
166 | free_config(bar->config); | 202 | free_config(bar->config); |
167 | free_output(bar->output); | 203 | free_outputs(bar->outputs); |
168 | free_status_line(bar->status); | 204 | free_status_line(bar->status); |
169 | 205 | ||
170 | /* close sockets/pipes */ | 206 | /* close sockets/pipes */ |
diff --git a/swaybar/config.c b/swaybar/config.c index 92251831..fddea791 100644 --- a/swaybar/config.c +++ b/swaybar/config.c | |||
@@ -51,6 +51,8 @@ struct config *init_config() { | |||
51 | config->strip_workspace_numbers = false; | 51 | config->strip_workspace_numbers = false; |
52 | config->binding_mode_indicator = true; | 52 | config->binding_mode_indicator = true; |
53 | config->workspace_buttons = true; | 53 | config->workspace_buttons = true; |
54 | config->all_outputs = false; | ||
55 | config->outputs = create_list(); | ||
54 | 56 | ||
55 | /* height */ | 57 | /* height */ |
56 | config->height = 0; | 58 | config->height = 0; |
diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 4104103d..312c79b9 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c | |||
@@ -11,7 +11,7 @@ static 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_bar, *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, *outputs; |
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_bar", &hidden_bar); | 17 | json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); |
@@ -25,6 +25,7 @@ static void ipc_parse_config(struct config *config, const char *payload) { | |||
25 | json_object_object_get_ex(bar_config, "verbose", &verbose); | 25 | json_object_object_get_ex(bar_config, "verbose", &verbose); |
26 | json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol); | 26 | json_object_object_get_ex(bar_config, "separator_symbol", &sep_symbol); |
27 | json_object_object_get_ex(bar_config, "colors", &colors); | 27 | json_object_object_get_ex(bar_config, "colors", &colors); |
28 | json_object_object_get_ex(bar_config, "outputs", &outputs); | ||
28 | 29 | ||
29 | if (status_command) { | 30 | if (status_command) { |
30 | free(config->status_command); | 31 | free(config->status_command); |
@@ -61,6 +62,31 @@ static void ipc_parse_config(struct config *config, const char *payload) { | |||
61 | config->height = json_object_get_int(bar_height); | 62 | config->height = json_object_get_int(bar_height); |
62 | } | 63 | } |
63 | 64 | ||
65 | // free previous outputs list | ||
66 | int i; | ||
67 | for (i = 0; i < config->outputs->length; ++i) { | ||
68 | free(config->outputs->items[i]); | ||
69 | } | ||
70 | list_free(config->outputs); | ||
71 | config->outputs = create_list(); | ||
72 | |||
73 | if (outputs) { | ||
74 | int length = json_object_array_length(outputs); | ||
75 | json_object *output; | ||
76 | const char *output_str; | ||
77 | for (i = 0; i < length; ++i) { | ||
78 | output = json_object_array_get_idx(outputs, i); | ||
79 | output_str = json_object_get_string(output); | ||
80 | if (strcmp("*", output_str) == 0) { | ||
81 | config->all_outputs = true; | ||
82 | break; | ||
83 | } | ||
84 | list_add(config->outputs, strdup(output_str)); | ||
85 | } | ||
86 | } else { | ||
87 | config->all_outputs = true; | ||
88 | } | ||
89 | |||
64 | if (colors) { | 90 | if (colors) { |
65 | json_object *background, *statusline, *separator; | 91 | json_object *background, *statusline, *separator; |
66 | json_object *focused_workspace_border, *focused_workspace_bg, *focused_workspace_text; | 92 | json_object *focused_workspace_border, *focused_workspace_bg, *focused_workspace_text; |
@@ -151,10 +177,14 @@ static void ipc_parse_config(struct config *config, const char *payload) { | |||
151 | } | 177 | } |
152 | 178 | ||
153 | static void ipc_update_workspaces(struct bar *bar) { | 179 | static void ipc_update_workspaces(struct bar *bar) { |
154 | if (bar->output->workspaces) { | 180 | int i; |
155 | free_workspaces(bar->output->workspaces); | 181 | for (i = 0; i < bar->outputs->length; ++i) { |
182 | struct output *output = bar->outputs->items[i]; | ||
183 | if (output->workspaces) { | ||
184 | free_workspaces(output->workspaces); | ||
185 | } | ||
186 | output->workspaces = create_list(); | ||
156 | } | 187 | } |
157 | bar->output->workspaces = create_list(); | ||
158 | 188 | ||
159 | uint32_t len = 0; | 189 | uint32_t len = 0; |
160 | char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len); | 190 | char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_WORKSPACES, NULL, &len); |
@@ -164,7 +194,6 @@ static void ipc_update_workspaces(struct bar *bar) { | |||
164 | return; | 194 | return; |
165 | } | 195 | } |
166 | 196 | ||
167 | int i; | ||
168 | int length = json_object_array_length(results); | 197 | int length = json_object_array_length(results); |
169 | json_object *ws_json; | 198 | json_object *ws_json; |
170 | json_object *num, *name, *visible, *focused, *out, *urgent; | 199 | json_object *num, *name, *visible, *focused, *out, *urgent; |
@@ -178,14 +207,18 @@ static void ipc_update_workspaces(struct bar *bar) { | |||
178 | json_object_object_get_ex(ws_json, "output", &out); | 207 | json_object_object_get_ex(ws_json, "output", &out); |
179 | json_object_object_get_ex(ws_json, "urgent", &urgent); | 208 | json_object_object_get_ex(ws_json, "urgent", &urgent); |
180 | 209 | ||
181 | if (strcmp(json_object_get_string(out), bar->output->name) == 0) { | 210 | int j; |
182 | struct workspace *ws = malloc(sizeof(struct workspace)); | 211 | for (j = 0; j < bar->outputs->length; ++j) { |
183 | ws->num = json_object_get_int(num); | 212 | struct output *output = bar->outputs->items[j]; |
184 | ws->name = strdup(json_object_get_string(name)); | 213 | if (strcmp(json_object_get_string(out), output->name) == 0) { |
185 | ws->visible = json_object_get_boolean(visible); | 214 | struct workspace *ws = malloc(sizeof(struct workspace)); |
186 | ws->focused = json_object_get_boolean(focused); | 215 | ws->num = json_object_get_int(num); |
187 | ws->urgent = json_object_get_boolean(urgent); | 216 | ws->name = strdup(json_object_get_string(name)); |
188 | list_add(bar->output->workspaces, ws); | 217 | ws->visible = json_object_get_boolean(visible); |
218 | ws->focused = json_object_get_boolean(focused); | ||
219 | ws->urgent = json_object_get_boolean(urgent); | ||
220 | list_add(output->workspaces, ws); | ||
221 | } | ||
189 | } | 222 | } |
190 | } | 223 | } |
191 | 224 | ||
@@ -193,22 +226,58 @@ static void ipc_update_workspaces(struct bar *bar) { | |||
193 | free(res); | 226 | free(res); |
194 | } | 227 | } |
195 | 228 | ||
196 | void ipc_bar_init(struct bar *bar, int outputi, const char *bar_id) { | 229 | void ipc_bar_init(struct bar *bar, const char *bar_id) { |
197 | uint32_t len = 0; | 230 | // Get bar config |
198 | char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_OUTPUTS, NULL, &len); | 231 | uint32_t len = strlen(bar_id); |
199 | json_object *outputs = json_tokener_parse(res); | 232 | char *res = ipc_single_command(bar->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len); |
200 | json_object *info = json_object_array_get_idx(outputs, outputi); | 233 | |
201 | json_object *name; | 234 | ipc_parse_config(bar->config, res); |
202 | json_object_object_get_ex(info, "name", &name); | ||
203 | bar->output->name = strdup(json_object_get_string(name)); | ||
204 | free(res); | 235 | free(res); |
205 | json_object_put(outputs); | ||
206 | 236 | ||
207 | len = strlen(bar_id); | 237 | // Get outputs |
208 | res = ipc_single_command(bar->ipc_socketfd, IPC_GET_BAR_CONFIG, bar_id, &len); | 238 | len = 0; |
239 | res = ipc_single_command(bar->ipc_socketfd, IPC_GET_OUTPUTS, NULL, &len); | ||
240 | json_object *outputs = json_tokener_parse(res); | ||
241 | int i; | ||
242 | int length = json_object_array_length(outputs); | ||
243 | json_object *output, *output_name, *output_active; | ||
244 | const char *name; | ||
245 | bool active; | ||
246 | for (i = 0; i < length; ++i) { | ||
247 | output = json_object_array_get_idx(outputs, i); | ||
248 | json_object_object_get_ex(output, "name", &output_name); | ||
249 | json_object_object_get_ex(output, "active", &output_active); | ||
250 | name = json_object_get_string(output_name); | ||
251 | active = json_object_get_boolean(output_active); | ||
252 | if (!active) { | ||
253 | continue; | ||
254 | } | ||
209 | 255 | ||
210 | ipc_parse_config(bar->config, res); | 256 | bool use_output = false; |
257 | if (bar->config->all_outputs) { | ||
258 | use_output = true; | ||
259 | } else { | ||
260 | int j = 0; | ||
261 | for (j = 0; j < bar->config->outputs->length; ++j) { | ||
262 | const char *conf_name = bar->config->outputs->items[i]; | ||
263 | if (strcasecmp(name, conf_name) == 0) { | ||
264 | use_output = true; | ||
265 | break; | ||
266 | } | ||
267 | } | ||
268 | } | ||
269 | |||
270 | if (!use_output) { | ||
271 | continue; | ||
272 | } | ||
273 | |||
274 | // add bar to the output | ||
275 | struct output *bar_output = new_output(name); | ||
276 | bar_output->idx = i; | ||
277 | list_add(bar->outputs, bar_output); | ||
278 | } | ||
211 | free(res); | 279 | free(res); |
280 | json_object_put(outputs); | ||
212 | 281 | ||
213 | const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; | 282 | const char *subscribe_json = "[ \"workspace\", \"mode\" ]"; |
214 | len = strlen(subscribe_json); | 283 | len = strlen(subscribe_json); |
diff --git a/swaybar/main.c b/swaybar/main.c index c6bbc7a5..d7534f5d 100644 --- a/swaybar/main.c +++ b/swaybar/main.c | |||
@@ -35,7 +35,7 @@ int main(int argc, char **argv) { | |||
35 | }; | 35 | }; |
36 | 36 | ||
37 | const char *usage = | 37 | const char *usage = |
38 | "Usage: swaybar [options...] <output>\n" | 38 | "Usage: swaybar [options...]\n" |
39 | "\n" | 39 | "\n" |
40 | " -h, --help Show help message and quit.\n" | 40 | " -h, --help Show help message and quit.\n" |
41 | " -v, --version Show the version number and quit.\n" | 41 | " -v, --version Show the version number and quit.\n" |
@@ -95,15 +95,9 @@ int main(int argc, char **argv) { | |||
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | if (argc == optind) { | ||
99 | sway_abort("No output index provided"); | ||
100 | } | ||
101 | |||
102 | int desired_output = atoi(argv[optind]); | ||
103 | |||
104 | signal(SIGTERM, sig_handler); | 98 | signal(SIGTERM, sig_handler); |
105 | 99 | ||
106 | bar_setup(&swaybar, socket_path, bar_id, desired_output); | 100 | bar_setup(&swaybar, socket_path, bar_id); |
107 | 101 | ||
108 | free(socket_path); | 102 | free(socket_path); |
109 | free(bar_id); | 103 | free(bar_id); |