From d0b54e932b59baa71b54d842b249400db74ce79b Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sun, 30 Sep 2018 15:09:09 +0100 Subject: swaybar: save id upon startup This adds an id property to the bar, which will be used to filter barconfig_update events --- include/swaybar/bar.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'include/swaybar/bar.h') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index de234111..d29db31e 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -46,6 +46,8 @@ struct swaybar_hotspot { }; struct swaybar { + char *id; + struct wl_display *display; struct wl_compositor *compositor; struct zwlr_layer_shell_v1 *layer_shell; @@ -96,7 +98,7 @@ struct swaybar_workspace { bool urgent; }; -bool bar_setup(struct swaybar *bar, const char *socket_path, const char *bar_id); +bool bar_setup(struct swaybar *bar, const char *socket_path); void bar_run(struct swaybar *bar); void bar_teardown(struct swaybar *bar); -- cgit v1.2.3-70-g09d2 From 18eaf452245d47461070894b4324d2afa47b0b05 Mon Sep 17 00:00:00 2001 From: Ian Fan Date: Sat, 6 Oct 2018 19:02:12 +0100 Subject: swaybar: annotate wl_list properties in definitions --- include/swaybar/bar.h | 12 ++++++------ include/swaybar/config.h | 2 +- include/swaybar/i3bar.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'include/swaybar/bar.h') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index d29db31e..3c1a236d 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -37,7 +37,7 @@ enum hotspot_event_handling { }; struct swaybar_hotspot { - struct wl_list link; + struct wl_list link; // swaybar_output::hotspots int x, y, width, height; enum hotspot_event_handling (*callback)(struct swaybar_output *output, int x, int y, enum x11_button button, void *data); @@ -62,11 +62,11 @@ struct swaybar { int ipc_event_socketfd; int ipc_socketfd; - struct wl_list outputs; + struct wl_list outputs; // swaybar_output::link }; struct swaybar_output { - struct wl_list link; + struct wl_list link; // swaybar::outputs struct swaybar *bar; struct wl_output *output; struct zxdg_output_v1 *xdg_output; @@ -74,8 +74,8 @@ struct swaybar_output { struct zwlr_layer_surface_v1 *layer_surface; uint32_t wl_name; - struct wl_list workspaces; - struct wl_list hotspots; + struct wl_list workspaces; // swaybar_workspace::link + struct wl_list hotspots; // swaybar_hotspot::link char *name; bool focused; @@ -90,7 +90,7 @@ struct swaybar_output { }; struct swaybar_workspace { - struct wl_list link; + struct wl_list link; // swaybar_output::workspaces int num; char *name; bool focused; diff --git a/include/swaybar/config.h b/include/swaybar/config.h index d0336c27..99948463 100644 --- a/include/swaybar/config.h +++ b/include/swaybar/config.h @@ -13,7 +13,7 @@ struct box_colors { }; struct config_output { - struct wl_list link; + struct wl_list link; // swaybar_config::outputs char *name; size_t index; }; diff --git a/include/swaybar/i3bar.h b/include/swaybar/i3bar.h index 12d9b317..d4a48e07 100644 --- a/include/swaybar/i3bar.h +++ b/include/swaybar/i3bar.h @@ -5,7 +5,7 @@ #include "status_line.h" struct i3bar_block { - struct wl_list link; + struct wl_list link; // status_link::blocks int ref_count; char *full_text, *short_text, *align; bool urgent; -- cgit v1.2.3-70-g09d2 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 --- include/swaybar/bar.h | 1 + swaybar/bar.c | 23 +++++++++++++---------- swaybar/render.c | 9 +-------- 3 files changed, 15 insertions(+), 18 deletions(-) (limited to 'include/swaybar/bar.h') diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h index 3c1a236d..72e0ca75 100644 --- a/include/swaybar/bar.h +++ b/include/swaybar/bar.h @@ -102,6 +102,7 @@ bool bar_setup(struct swaybar *bar, const char *socket_path); void bar_run(struct swaybar *bar); void bar_teardown(struct swaybar *bar); +void free_hotspots(struct wl_list *list); void free_workspaces(struct wl_list *list); #endif diff --git a/swaybar/bar.c b/swaybar/bar.c index f2dab738..e6c5f2f1 100644 --- a/swaybar/bar.c +++ b/swaybar/bar.c @@ -35,6 +35,17 @@ static void bar_init(struct swaybar *bar) { wl_list_init(&bar->outputs); } +void free_hotspots(struct wl_list *list) { + struct swaybar_hotspot *hotspot, *tmp; + wl_list_for_each_safe(hotspot, tmp, list, link) { + wl_list_remove(&hotspot->link); + if (hotspot->destroy) { + hotspot->destroy(hotspot->data); + } + free(hotspot); + } +} + void free_workspaces(struct wl_list *list) { struct swaybar_workspace *ws, *tmp; wl_list_for_each_safe(ws, tmp, list, link) { @@ -59,14 +70,8 @@ static void swaybar_output_free(struct swaybar_output *output) { wl_output_destroy(output->output); destroy_buffer(&output->buffers[0]); destroy_buffer(&output->buffers[1]); + free_hotspots(&output->hotspots); free_workspaces(&output->workspaces); - struct swaybar_hotspot *hotspot, *hotspot_tmp; - wl_list_for_each_safe(hotspot, hotspot_tmp, &output->hotspots, link) { - if (hotspot->destroy) { - hotspot->destroy(hotspot->data); - } - free(hotspot); - } wl_list_remove(&output->link); free(output->name); free(output); @@ -75,9 +80,7 @@ static void swaybar_output_free(struct swaybar_output *output) { static void set_output_dirty(struct swaybar_output *output) { if (output->frame_scheduled) { output->dirty = true; - return; - } - if (output->surface) { + } else if (output->surface) { render_frame(output); } } 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 'include/swaybar/bar.h') 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 'include/swaybar/bar.h') 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