From 19f0bf38640f4da609782442c901366617aa27fa Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 12 Oct 2018 20:18:04 +0100 Subject: swaybar: add free_hotspots helper function --- swaybar/render.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/render.c b/swaybar/render.c index dc31a5ea..2a06a79b 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -491,14 +491,7 @@ static const struct wl_callback_listener output_frame_listener = { void render_frame(struct swaybar_output *output) { assert(output->surface != NULL); - struct swaybar_hotspot *hotspot, *tmp; - wl_list_for_each_safe(hotspot, tmp, &output->hotspots, link) { - if (hotspot->destroy) { - hotspot->destroy(hotspot->data); - } - wl_list_remove(&hotspot->link); - free(hotspot); - } + free_hotspots(&output->hotspots); cairo_surface_t *recorder = cairo_recording_surface_create( CAIRO_CONTENT_COLOR_ALPHA, NULL); -- cgit v1.2.3-70-g09d2 From fed11d1c7b388e999414dd8cec4b8982ba5ce950 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 12 Oct 2018 20:23:01 +0100 Subject: swaybar: move mode & mode_pango_markup to bar struct This distinguishes the binding mode from the distinct config mode, as well as removing mode_pango_markup from the config struct where it should not be present. --- include/swaybar/bar.h | 2 ++ include/swaybar/config.h | 1 - swaybar/bar.c | 1 + swaybar/ipc.c | 11 +++-------- swaybar/render.c | 14 +++++++++----- 5 files changed, 15 insertions(+), 14 deletions(-) (limited to 'swaybar/render.c') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 72e0ca75..593f4f6d 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -47,6 +47,8 @@ struct swaybar_hotspot { struct swaybar { char *id; + char *mode; + bool mode_pango_markup; struct wl_display *display; struct wl_compositor *compositor; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 99948463..68ee2087 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -31,7 +31,6 @@ struct swaybar_config { char *font; char *sep_symbol; char *mode; - bool mode_pango_markup; bool strip_workspace_numbers; bool binding_mode_indicator; bool wrap_scroll; diff --git a/swaybar/bar.c b/swaybar/bar.c index ecf1bf82..77294136 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -631,4 +631,5 @@ void bar_teardown(struct swaybar *bar) { status_line_free(bar->status); } free(bar->id); + free(bar->mode); } diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 26b7eca6..8568f957 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -386,12 +386,8 @@ bool handle_ipc_readable(struct swaybar *bar) { json_object *json_change, *json_pango_markup; if (json_object_object_get_ex(result, "change", &json_change)) { const char *change = json_object_get_string(json_change); - free(bar->config->mode); - if (strcmp(change, "default") == 0) { - bar->config->mode = NULL; - } else { - bar->config->mode = strdup(change); - } + free(bar->mode); + bar->mode = strcmp(change, "default") != 0 ? strdup(change) : NULL; } else { wlr_log(WLR_ERROR, "failed to parse response"); json_object_put(result); @@ -400,8 +396,7 @@ bool handle_ipc_readable(struct swaybar *bar) { } if (json_object_object_get_ex(result, "pango_markup", &json_pango_markup)) { - bar->config->mode_pango_markup = json_object_get_boolean( - json_pango_markup); + bar->mode_pango_markup = json_object_get_boolean(json_pango_markup); } json_object_put(result); break; diff --git a/swaybar/render.c b/swaybar/render.c index 2a06a79b..d226ba32 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -296,11 +296,15 @@ static uint32_t render_status_line(cairo_t *cairo, static uint32_t render_binding_mode_indicator(cairo_t *cairo, struct swaybar_output *output, double x) { + const char *mode = output->bar->mode; + if (!mode) { + return 0; + } + struct swaybar_config *config = output->bar->config; - const char *mode = config->mode; int text_width, text_height; get_text_size(cairo, config->font, &text_width, &text_height, NULL, - output->scale, config->mode_pango_markup, + output->scale, output->bar->mode_pango_markup, "%s", mode); int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; @@ -333,8 +337,8 @@ static uint32_t render_binding_mode_indicator(cairo_t *cairo, double text_y = height / 2.0 - text_height / 2.0; cairo_set_source_u32(cairo, config->colors.binding_mode.text); cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); - pango_printf(cairo, config->font, output->scale, config->mode_pango_markup, - "%s", mode); + pango_printf(cairo, config->font, output->scale, + output->bar->mode_pango_markup, "%s", mode); return output->height; } @@ -465,7 +469,7 @@ static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) { max_height = h > max_height ? h : max_height; } } - if (config->binding_mode_indicator && config->mode) { + if (config->binding_mode_indicator) { uint32_t h = render_binding_mode_indicator(cairo, output, x); max_height = h > max_height ? h : max_height; } -- cgit v1.2.3-70-g09d2 From bcc61e5147fb57a3b4bfb9a2a33065a0cf6da67b Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Fri, 12 Oct 2018 20:32:48 +0100 Subject: swaybar: handle mode/hidden_state changes As well as adding the hidden_state property to the bar config struct, this commit handles barconfig_update events when the mode or hidden_state changes, and uses a new function determine_bar_visibility to hide or show the bar as required, using, respectively, destroy_layer_surface, which is also newly added, and add_layer_surface, which has been changed to allow dynamically adding the surface. --- include/swaybar/bar.h | 18 ++++++++++++++ include/swaybar/config.h | 1 + swaybar/bar.c | 62 ++++++++++++++++++++++++++++++++++++++++++------ swaybar/config.c | 4 +++- swaybar/ipc.c | 46 +++++++++++++++++++++++++++++++++-- swaybar/render.c | 7 +++++- 6 files changed, 127 insertions(+), 11 deletions(-) (limited to 'swaybar/render.c') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 593f4f6d..9ff3fe7b 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -50,6 +50,11 @@ struct swaybar { char *mode; bool mode_pango_markup; + // only relevant when bar is in "hide" mode + bool visible_by_modifier; + bool visible_by_urgency; + bool visible; + struct wl_display *display; struct wl_compositor *compositor; struct zwlr_layer_shell_v1 *layer_shell; @@ -104,6 +109,19 @@ bool bar_setup(struct swaybar *bar, const char *socket_path); void bar_run(struct swaybar *bar); void bar_teardown(struct swaybar *bar); +/* + * Determines whether the bar should be visible and changes it to be so. + * If the current visibility of the bar is the different to what it should be, + * then it adds or destroys the layer surface as required, + * as well as sending the cont or stop signal to the status command. + * If the current visibility of the bar is already what it should be, + * then this function is a no-op, unless moving_layer is true, which occurs + * when the bar changes from "hide" to "dock" mode or vice versa, and the bar + * needs to be destroyed and re-added in order to change its layer. + * + * Returns true if the bar is now visible, otherwise false. + */ +bool determine_bar_visibility(struct swaybar *bar, bool moving_layer); void free_hotspots(struct wl_list *list); void free_workspaces(struct wl_list *list); diff --git a/include/swaybar/config.h b/include/swaybar/config.h index 68ee2087..10904bca 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -31,6 +31,7 @@ struct swaybar_config { char *font; char *sep_symbol; char *mode; + char *hidden_state; bool strip_workspace_numbers; bool binding_mode_indicator; bool wrap_scroll; diff --git a/swaybar/bar.c b/swaybar/bar.c index 77294136..6894383d 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -32,6 +32,7 @@ static void bar_init(struct swaybar *bar) { bar->config = init_config(); + bar->visible = true; wl_list_init(&bar->outputs); } @@ -338,21 +339,65 @@ const struct wl_seat_listener seat_listener = { }; static void add_layer_surface(struct swaybar_output *output) { - if (output->surface != NULL) { + if (output->layer_surface) { return; } struct swaybar *bar = output->bar; - output->surface = wl_compositor_create_surface(bar->compositor); - assert(output->surface); + struct swaybar_config *config = bar->config; + bool hidden = strcmp(config->mode, "hide") == 0; output->layer_surface = zwlr_layer_shell_v1_get_layer_surface( bar->layer_shell, output->surface, output->output, + hidden ? ZWLR_LAYER_SHELL_V1_LAYER_TOP : ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, "panel"); assert(output->layer_surface); zwlr_layer_surface_v1_add_listener(output->layer_surface, &layer_surface_listener, output); - zwlr_layer_surface_v1_set_anchor(output->layer_surface, - bar->config->position); + + zwlr_layer_surface_v1_set_anchor(output->layer_surface, config->position); + if (hidden) { + zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, -1); + } +} + +static void destroy_layer_surface(struct swaybar_output *output) { + if (!output->layer_surface) { + return; + } + zwlr_layer_surface_v1_destroy(output->layer_surface); + wl_surface_attach(output->surface, NULL, 0, 0); // detach buffer + output->layer_surface = NULL; + output->height = 0; + output->width = 0; + output->frame_scheduled = false; +} + +bool determine_bar_visibility(struct swaybar *bar, bool moving_layer) { + struct swaybar_config *config = bar->config; + bool visible = !(strcmp(config->mode, "invisible") == 0 || + (strcmp(config->mode, config->hidden_state) == 0 // both "hide" + && !bar->visible_by_modifier && !bar->visible_by_urgency)); + + struct swaybar_output *output; + if (visible == bar->visible) { + if (visible && moving_layer) { + // need to destroy layer surface to move to a different layer + wl_list_for_each(output, &bar->outputs, link) { + destroy_layer_surface(output); + add_layer_surface(output); + } + } + } else { + bar->visible = visible; + wl_list_for_each(output, &bar->outputs, link) { + if (visible) { + add_layer_surface(output); + } else { + destroy_layer_surface(output); + } + } + } + return visible; } static bool bar_uses_output(struct swaybar *bar, const char *name) { @@ -423,8 +468,11 @@ static void xdg_output_handle_done(void *data, wl_list_remove(&output->link); wl_list_insert(&bar->outputs, &output->link); - add_layer_surface(output); - set_output_dirty(output); + output->surface = wl_compositor_create_surface(bar->compositor); + assert(output->surface); + if (bar->visible) { + add_layer_surface(output); + } } } 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) { config->pango_markup = false; config->position = parse_position("bottom"); config->font = strdup("monospace 10"); - config->mode = NULL; + config->mode = strdup("dock"); + config->hidden_state = strdup("hide"); config->sep_symbol = NULL; config->strip_workspace_numbers = false; config->binding_mode_indicator = true; @@ -84,6 +85,7 @@ void free_config(struct swaybar_config *config) { free(config->status_command); free(config->font); free(config->mode); + free(config->hidden_state); free(config->sep_symbol); for (int i = 0; i < config->bindings->length; i++) { struct swaybar_binding *binding = config->bindings->items[i]; diff --git a/swaybar/ipc.c b/swaybar/ipc.c index 6013c2de..56379fdb 100644 --- a/swaybar/ipc.c +++ b/swaybar/ipc.c @@ -152,12 +152,12 @@ static bool ipc_parse_config( json_object_put(bar_config); return false; } - json_object *markup, *mode, *hidden_bar, *position, *status_command; + json_object *markup, *mode, *hidden_state, *position, *status_command; json_object *font, *bar_height, *wrap_scroll, *workspace_buttons, *strip_workspace_numbers; json_object *binding_mode_indicator, *verbose, *colors, *sep_symbol, *outputs; json_object *bindings; json_object_object_get_ex(bar_config, "mode", &mode); - json_object_object_get_ex(bar_config, "hidden_bar", &hidden_bar); + json_object_object_get_ex(bar_config, "hidden_state", &hidden_state); json_object_object_get_ex(bar_config, "position", &position); json_object_object_get_ex(bar_config, "status_command", &status_command); json_object_object_get_ex(bar_config, "font", &font); @@ -220,6 +220,14 @@ static bool ipc_parse_config( list_add(config->bindings, binding); } } + if (hidden_state) { + free(config->hidden_state); + config->hidden_state = strdup(json_object_get_string(hidden_state)); + } + if (mode) { + free(config->mode); + config->mode = strdup(json_object_get_string(mode)); + } struct config_output *output, *tmp; wl_list_for_each_safe(output, tmp, &config->outputs, link) { @@ -367,6 +375,37 @@ bool ipc_initialize(struct swaybar *bar) { return true; } +static bool handle_barconfig_update(struct swaybar *bar, + json_object *json_config) { + json_object *json_id; + json_object_object_get_ex(json_config, "id", &json_id); + const char *id = json_object_get_string(json_id); + if (strcmp(id, bar->id) != 0) { + return false; + } + + struct swaybar_config *config = bar->config; + + json_object *json_state; + json_object_object_get_ex(json_config, "hidden_state", &json_state); + const char *new_state = json_object_get_string(json_state); + char *old_state = config->hidden_state; + if (strcmp(new_state, old_state) != 0) { + wlr_log(WLR_DEBUG, "Changing bar hidden state to %s", new_state); + free(old_state); + config->hidden_state = strdup(new_state); + return determine_bar_visibility(bar, false); + } + + free(config->mode); + json_object *json_mode; + json_object_object_get_ex(json_config, "mode", &json_mode); + config->mode = strdup(json_object_get_string(json_mode)); + wlr_log(WLR_DEBUG, "Changing bar mode to %s", config->mode); + + return determine_bar_visibility(bar, true); +} + bool handle_ipc_readable(struct swaybar *bar) { struct ipc_response *resp = ipc_recv_response(bar->ipc_event_socketfd); if (!resp) { @@ -402,6 +441,9 @@ bool handle_ipc_readable(struct swaybar *bar) { } break; } + case IPC_EVENT_BARCONFIG_UPDATE: + bar_is_dirty = handle_barconfig_update(bar, result); + break; default: bar_is_dirty = false; break; diff --git a/swaybar/render.c b/swaybar/render.c index d226ba32..670630cf 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -494,6 +494,9 @@ static const struct wl_callback_listener output_frame_listener = { void render_frame(struct swaybar_output *output) { assert(output->surface != NULL); + if (!output->layer_surface) { + return; + } free_hotspots(&output->hotspots); @@ -519,7 +522,9 @@ void render_frame(struct swaybar_output *output) { if (height != output->height) { // Reconfigure surface zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); - zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); + if (strcmp(output->bar->config->mode, "dock") == 0) { + zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); + } // TODO: this could infinite loop if the compositor assigns us a // different height than what we asked for wl_surface_commit(output->surface); -- cgit v1.2.3-70-g09d2 From 4dba7c084acb6ca1c9d220f8eac918c046c199ad Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sat, 13 Oct 2018 11:56:56 +0100 Subject: swaybar: when hiding bar, save old height to be restored upon reshow Previously, when the bar was hidden, the height would be set to 0. This meant that if the bar was empty upon reshow, it would not render since the height was still 0, which made it seem there was a problem. Now, the height is not reset, but the width is, to indicate upon reshow that the layer surface needed reconfiguring. --- swaybar/bar.c | 1 - swaybar/render.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'swaybar/render.c') diff --git a/swaybar/bar.c b/swaybar/bar.c index f636f0c9..9f72c94c 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -367,7 +367,6 @@ static void destroy_layer_surface(struct swaybar_output *output) { zwlr_layer_surface_v1_destroy(output->layer_surface); wl_surface_attach(output->surface, NULL, 0, 0); // detach buffer output->layer_surface = NULL; - output->height = 0; output->width = 0; output->frame_scheduled = false; } diff --git a/swaybar/render.c b/swaybar/render.c index 670630cf..097eb462 100644 --- a/swaybar/render.c +++ b/swaybar/render.c @@ -519,7 +519,7 @@ void render_frame(struct swaybar_output *output) { if (config_height >= 0 && height < (uint32_t)config_height) { height = config_height; } - if (height != output->height) { + if (height != output->height || output->width == 0) { // Reconfigure surface zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); if (strcmp(output->bar->config->mode, "dock") == 0) { -- cgit v1.2.3-70-g09d2