From ede27eabc53dc926aa1932c2a58c06def1000f86 Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Fri, 18 Dec 2015 17:43:03 +0100 Subject: [PATCH 1/2] Reload swaybar/swaybg on config reload. This works by tracking the pids of the child processes in the related output container and terminating the processes and spawning new ones on a config reload. Should solve: #347 --- include/config.h | 2 + include/container.h | 6 ++ sway/commands.c | 9 +++ sway/config.c | 147 +++++++++++++++++++++++++++++++------------- sway/container.c | 5 ++ 5 files changed, 125 insertions(+), 44 deletions(-) diff --git a/include/config.h b/include/config.h index 325629088..1f25a0cd2 100644 --- a/include/config.h +++ b/include/config.h @@ -184,6 +184,8 @@ int sway_mouse_binding_cmp(const void *a, const void *b); int sway_mouse_binding_cmp_buttons(const void *a, const void *b); void free_sway_mouse_binding(struct sway_mouse_binding *smb); +void load_swaybars(swayc_t *output, int output_idx); + /** * Allocate and initialize default bar configuration. */ diff --git a/include/container.h b/include/container.h index 9a67a6894..d76160dea 100644 --- a/include/container.h +++ b/include/container.h @@ -1,5 +1,6 @@ #ifndef _SWAY_CONTAINER_H #define _SWAY_CONTAINER_H +#include #include typedef struct sway_container swayc_t; @@ -81,6 +82,11 @@ struct sway_container { char *class; char *app_id; + // Used by output containers to keep track of swaybar/swaybg child + // processes. + list_t *bar_pids; + pid_t bg_pid; + int gaps; list_t *children; diff --git a/sway/commands.c b/sway/commands.c index 24d56052e..13bc7dc27 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -1094,6 +1094,15 @@ static struct cmd_results *cmd_reload(int argc, char **argv) { } if (!load_config(NULL)) return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); + int i; + swayc_t *cont = NULL; + for (i = 0; i < root_container.children->length; ++i) { + cont = root_container.children->items[i]; + if (cont->type == C_OUTPUT) { + load_swaybars(cont, i); + } + } + arrange_windows(&root_container, -1, -1); return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/config.c b/sway/config.c index 970225f49..23fe5388e 100644 --- a/sway/config.c +++ b/sway/config.c @@ -3,6 +3,9 @@ #include #include #include +#include +#include +#include #include "wayland-desktop-shell-server-protocol.h" #include "readline.h" #include "stringop.h" @@ -360,6 +363,91 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { } } +static void invoke_swaybar(swayc_t *output, struct bar_config *bar, int output_i) { + sway_log(L_DEBUG, "Invoking swaybar for output %s[%d] and bar %s", output->name, output_i, bar->id); + + size_t bufsize = 4; + char output_id[bufsize]; + snprintf(output_id, bufsize, "%d", output_i); + output_id[bufsize-1] = 0; + + char *const cmd[] = { + "swaybar", + "-b", + bar->id, + output_id, + NULL, + }; + + pid_t *pid = malloc(sizeof(pid_t)); + *pid = fork(); + if (*pid == 0) { + execvp(cmd[0], cmd); + } + + // add swaybar pid to output + list_add(output->bar_pids, pid); +} + +static void terminate_swaybars(list_t *pids) { + int i, ret; + pid_t *pid; + for (i = 0; i < pids->length; ++i) { + pid = pids->items[i]; + ret = kill(*pid, SIGTERM); + if (ret != 0) { + sway_log(L_ERROR, "Unable to terminate swaybar [pid: %d]", *pid); + } else { + int status; + waitpid(*pid, &status, 0); + } + } + + // empty pids list + for (i = 0; i < pids->length; ++i) { + pid = pids->items[i]; + list_del(pids, i); + free(pid); + } +} + +void load_swaybars(swayc_t *output, int output_idx) { + // Check for bars + list_t *bars = create_list(); + struct bar_config *bar = NULL; + int i; + for (i = 0; i < config->bars->length; ++i) { + bar = config->bars->items[i]; + bool apply = false; + if (bar->outputs) { + int j; + for (j = 0; j < bar->outputs->length; ++j) { + char *o = bar->outputs->items[j]; + if (strcmp(o, "*") || strcasecmp(o, output->name)) { + apply = true; + break; + } + } + } else { + apply = true; + } + if (apply) { + list_add(bars, bar); + } + } + + // terminate swaybar processes previously spawned for this + // output. + terminate_swaybars(output->bar_pids); + + for (i = 0; i < bars->length; ++i) { + bar = bars->items[i]; + invoke_swaybar(output, bar, output_idx); + } + + list_free(bars); +} + void apply_output_config(struct output_config *oc, swayc_t *output) { if (oc && oc->width > 0 && oc->height > 0) { output->width = oc->width; @@ -407,6 +495,16 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { if (oc && oc->background) { + if (output->bg_pid != 0) { + int ret = kill(output->bg_pid, SIGTERM); + if (ret != 0) { + sway_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", output->bg_pid); + } else { + int status; + waitpid(output->bg_pid, &status, 0); + } + } + sway_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); size_t bufsize = 4; @@ -421,54 +519,15 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { oc->background_option, NULL, }; - if (fork() == 0) { + + output->bg_pid = fork(); + if (output->bg_pid == 0) { execvp(cmd[0], cmd); } } - // Check for a bar - struct bar_config *bar = NULL; - int i; - for (i = 0; i < config->bars->length; ++i) { - bar = config->bars->items[i]; - bool apply = false; - if (bar->outputs) { - int j; - for (j = 0; j < bar->outputs->length; ++j) { - char *o = bar->outputs->items[j]; - if (strcmp(o, "*") || strcasecmp(o, output->name)) { - apply = true; - break; - } - } - } else { - apply = true; - } - if (apply) { - break; - } else { - bar = NULL; - } - } - if (bar) { - sway_log(L_DEBUG, "Invoking swaybar for output %s[%d] and bar %s", output->name, i, bar->id); - - size_t bufsize = 4; - char output_id[bufsize]; - snprintf(output_id, bufsize, "%d", output_i); - output_id[bufsize-1] = 0; - - char *const cmd[] = { - "swaybar", - "-b", - bar->id, - output_id, - NULL, - }; - if (fork() == 0) { - execvp(cmd[0], cmd); - } - } + // load swaybars for output + load_swaybars(output, output_i); } char *do_var_replacement(char *str) { diff --git a/sway/container.c b/sway/container.c index 36056ff7e..395eb04d1 100644 --- a/sway/container.c +++ b/sway/container.c @@ -60,6 +60,9 @@ static void free_swayc(swayc_t *cont) { if (cont->app_id) { free(cont->app_id); } + if (cont->bar_pids) { + free_flat_list(cont->bar_pids); + } free(cont); } @@ -109,6 +112,8 @@ swayc_t *new_output(wlc_handle handle) { output->width = size->w; output->height = size->h; output->unmanaged = create_list(); + output->bar_pids = create_list(); + output->bg_pid = 0; apply_output_config(oc, output); add_child(&root_container, output); From 90ff36cab8657272b6727af69bab49dba463d6ba Mon Sep 17 00:00:00 2001 From: Mikkel Oscar Lyderik Date: Fri, 18 Dec 2015 18:02:39 +0100 Subject: [PATCH 2/2] Terminate children when freeing output container --- include/config.h | 2 ++ sway/config.c | 20 ++++++++++++-------- sway/container.c | 4 ++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/include/config.h b/include/config.h index 1f25a0cd2..b89ad5530 100644 --- a/include/config.h +++ b/include/config.h @@ -185,6 +185,8 @@ int sway_mouse_binding_cmp_buttons(const void *a, const void *b); void free_sway_mouse_binding(struct sway_mouse_binding *smb); void load_swaybars(swayc_t *output, int output_idx); +void terminate_swaybars(list_t *pids); +void terminate_swaybg(pid_t pid); /** * Allocate and initialize default bar configuration. diff --git a/sway/config.c b/sway/config.c index 23fe5388e..928d35a83 100644 --- a/sway/config.c +++ b/sway/config.c @@ -389,7 +389,7 @@ static void invoke_swaybar(swayc_t *output, struct bar_config *bar, int output_i list_add(output->bar_pids, pid); } -static void terminate_swaybars(list_t *pids) { +void terminate_swaybars(list_t *pids) { int i, ret; pid_t *pid; for (i = 0; i < pids->length; ++i) { @@ -411,6 +411,16 @@ static void terminate_swaybars(list_t *pids) { } } +void terminate_swaybg(pid_t pid) { + int ret = kill(pid, SIGTERM); + if (ret != 0) { + sway_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", pid); + } else { + int status; + waitpid(pid, &status, 0); + } +} + void load_swaybars(swayc_t *output, int output_idx) { // Check for bars list_t *bars = create_list(); @@ -496,13 +506,7 @@ void apply_output_config(struct output_config *oc, swayc_t *output) { if (oc && oc->background) { if (output->bg_pid != 0) { - int ret = kill(output->bg_pid, SIGTERM); - if (ret != 0) { - sway_log(L_ERROR, "Unable to terminate swaybg [pid: %d]", output->bg_pid); - } else { - int status; - waitpid(output->bg_pid, &status, 0); - } + terminate_swaybg(output->bg_pid); } sway_log(L_DEBUG, "Setting background for output %d to %s", output_i, oc->background); diff --git a/sway/container.c b/sway/container.c index 395eb04d1..b85d21144 100644 --- a/sway/container.c +++ b/sway/container.c @@ -61,8 +61,12 @@ static void free_swayc(swayc_t *cont) { free(cont->app_id); } if (cont->bar_pids) { + terminate_swaybars(cont->bar_pids); free_flat_list(cont->bar_pids); } + if (cont->bg_pid != 0) { + terminate_swaybg(cont->bg_pid); + } free(cont); }