From 6e0b29a65b99cdf193a615cb890f11aa1d17a97f Mon Sep 17 00:00:00 2001 From: Orestis Floros Date: Tue, 12 Jan 2021 08:41:19 +0100 Subject: [PATCH] i3bar: properly restart status command after config change --- RELEASE-NOTES-next | 1 + i3bar/include/child.h | 6 ++++++ i3bar/src/child.c | 4 ++-- i3bar/src/config.c | 1 - i3bar/src/ipc.c | 17 +++++++++++++++-- 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/RELEASE-NOTES-next b/RELEASE-NOTES-next index 9c9660431..8797bc932 100644 --- a/RELEASE-NOTES-next +++ b/RELEASE-NOTES-next @@ -25,3 +25,4 @@ strongly encouraged to upgrade. • fix duplicate bindcode after i3-config-wizard • clear pixmap before drawing to prevent visual grabage in clients using 'Shape' • i3bar: properly close file descriptors + • i3bar: properly restart status command after config change diff --git a/i3bar/include/child.h b/i3bar/include/child.h index adc638bed..ae523bc0f 100644 --- a/i3bar/include/child.h +++ b/i3bar/include/child.h @@ -42,6 +42,12 @@ typedef struct { bool click_events_init; } i3bar_child; +/* + * Remove all blocks from the given statusline. + * If free_resources is set, the fields of each status block will be free'd. + */ +void clear_statusline(struct statusline_head *head, bool free_resources); + /* * Start a child process with the specified command and reroute stdin. * We actually start a $SHELL to execute the command so we don't have to care diff --git a/i3bar/src/child.c b/i3bar/src/child.c index 1198186be..df4c66016 100644 --- a/i3bar/src/child.c +++ b/i3bar/src/child.c @@ -27,7 +27,7 @@ #include /* Global variables for child_*() */ -i3bar_child child; +i3bar_child child = {0}; #define DLOG_CHILD DLOG("%s: pid=%ld stopped=%d stop_signal=%d cont_signal=%d click_events=%d click_events_init=%d\n", \ __func__, (long)child.pid, child.stopped, child.stop_signal, child.cont_signal, child.click_events, child.click_events_init) @@ -66,7 +66,7 @@ int child_stdin; * Remove all blocks from the given statusline. * If free_resources is set, the fields of each status block will be free'd. */ -static void clear_statusline(struct statusline_head *head, bool free_resources) { +void clear_statusline(struct statusline_head *head, bool free_resources) { struct status_block *first; while (!TAILQ_EMPTY(head)) { first = TAILQ_FIRST(head); diff --git a/i3bar/src/config.c b/i3bar/src/config.c index 10847cd16..1cff085e2 100644 --- a/i3bar/src/config.c +++ b/i3bar/src/config.c @@ -184,7 +184,6 @@ static int config_string_cb(void *params_, const unsigned char *val, size_t _len if (!strcmp(cur_key, "status_command")) { DLOG("command = %.*s\n", len, val); - FREE(config.command); sasprintf(&config.command, "%.*s", len, val); return 1; } diff --git a/i3bar/src/ipc.c b/i3bar/src/ipc.c index ec5fc06a7..b3de145db 100644 --- a/i3bar/src/ipc.c +++ b/i3bar/src/ipc.c @@ -170,6 +170,15 @@ static void got_mode_event(char *event) { draw_bars(false); } +static bool strings_differ(char *a, char *b) { + const bool a_null = (a == NULL); + const bool b_null = (b == NULL); + if (a_null != b_null) { + return true; + } + return strcmp(a, b) != 0; +} + /* * Called, when a barconfig_update event arrives (i.e. i3 changed the bar hidden_state or mode) * @@ -190,8 +199,11 @@ static void got_bar_config_update(char *event) { /* update the configuration with the received settings */ DLOG("Received bar config update \"%s\"\n", event); - char *old_command = config.command ? sstrdup(config.command) : NULL; + + char *old_command = config.command; + config.command = NULL; bar_display_mode_t old_mode = config.hide_on_modifier; + parse_config_json(event); if (old_mode != config.hide_on_modifier) { reconfig_windows(true); @@ -202,8 +214,9 @@ static void got_bar_config_update(char *event) { init_colors(&(config.colors)); /* restart status command process */ - if (old_command && strcmp(old_command, config.command) != 0) { + if (strings_differ(old_command, config.command)) { kill_child(); + clear_statusline(&statusline_head, true); start_child(config.command); } free(old_command);