From db38b9bbf3cce4083c538209a7ce5ef1a1cf5f3f Mon Sep 17 00:00:00 2001 From: Ryan Dwyer Date: Fri, 25 May 2018 21:07:59 +1000 Subject: [PATCH] Clean up container title functions * Add and use lenient_strcat and lenient_strncat functions * Rename `concatenate_child_titles` function as that's no longer what it does * Rename `container_notify_child_title_changed` because we only need to notify that the tree structure has changed, not titles * Don't notify parents when a child changes its title * Update ancestor titles when changing a container's layout * Eg. create nested tabs and change the inner container to stacking * No need to store tree presentation in both container->name and formatted_title --- common/stringop.c | 14 ++++++ include/stringop.h | 5 ++ include/sway/tree/container.h | 6 ++- sway/commands/layout.c | 1 + sway/tree/container.c | 90 +++++++++++++++-------------------- sway/tree/layout.c | 12 ++--- sway/tree/view.c | 34 ++++--------- 7 files changed, 79 insertions(+), 83 deletions(-) diff --git a/common/stringop.c b/common/stringop.c index 4a37543d6..d9ae99256 100644 --- a/common/stringop.c +++ b/common/stringop.c @@ -55,6 +55,20 @@ void strip_quotes(char *str) { *end = '\0'; } +char *lenient_strcat(char *dest, const char *src) { + if (dest && src) { + return strcat(dest, src); + } + return dest; +} + +char *lenient_strncat(char *dest, const char *src, size_t len) { + if (dest && src) { + return strncat(dest, src, len); + } + return dest; +} + // strcmp that also handles null pointers. int lenient_strcmp(char *a, char *b) { if (a == b) { diff --git a/include/stringop.h b/include/stringop.h index 7c29a745e..e7f580112 100644 --- a/include/stringop.h +++ b/include/stringop.h @@ -1,5 +1,6 @@ #ifndef _SWAY_STRINGOP_H #define _SWAY_STRINGOP_H +#include #include "list.h" #if !HAVE_DECL_SETENV @@ -14,6 +15,10 @@ char *strip_whitespace(char *str); char *strip_comments(char *str); void strip_quotes(char *str); +// strcat that does nothing if dest or src is NULL +char *lenient_strcat(char *dest, const char *src); +char *lenient_strncat(char *dest, const char *src, size_t len); + // strcmp that also handles null pointers. int lenient_strcmp(char *a, char *b); diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 493c70e2b..a5f591ce5 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -216,7 +216,11 @@ void container_update_title_textures(struct sway_container *container); */ void container_calculate_title_height(struct sway_container *container); -void container_notify_child_title_changed(struct sway_container *container); +/** + * Notify a container that a tree modification has changed in its children, + * so the container can update its tree representation. + */ +void container_notify_subtree_changed(struct sway_container *container); /** * Return the height of a regular title bar. diff --git a/sway/commands/layout.c b/sway/commands/layout.c index 58728f168..6b44b0012 100644 --- a/sway/commands/layout.c +++ b/sway/commands/layout.c @@ -52,6 +52,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) { } } + container_notify_subtree_changed(parent); arrange_children_of(parent); return cmd_results_new(CMD_SUCCESS, NULL, NULL); diff --git a/sway/tree/container.c b/sway/tree/container.c index 9cf18f616..f29a9adc0 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -21,6 +21,7 @@ #include "sway/tree/view.h" #include "sway/tree/workspace.h" #include "log.h" +#include "stringop.h" static list_t *bfs_queue; @@ -774,42 +775,36 @@ void container_calculate_title_height(struct sway_container *container) { } /** - * Calculate and return the length of the concatenated child titles. - * An example concatenated title is: V[Terminal, Firefox] - * If buffer is not NULL, also populate the buffer with the concatenated title. + * Calculate and return the length of the tree representation. + * An example tree representation is: V[Terminal, Firefox] + * If buffer is not NULL, also populate the buffer with the representation. */ -static size_t concatenate_child_titles(struct sway_container *parent, - char *buffer) { - size_t len = 2; // V[ - if (buffer) { - switch (parent->layout) { - case L_VERT: - strcpy(buffer, "V["); - break; - case L_HORIZ: - strcpy(buffer, "H["); - break; - case L_TABBED: - strcpy(buffer, "T["); - break; - case L_STACKED: - strcpy(buffer, "S["); - break; - case L_FLOATING: - strcpy(buffer, "F["); - break; - case L_NONE: - strcpy(buffer, "D["); - break; - } +static size_t get_tree_representation(struct sway_container *parent, char *buffer) { + size_t len = 2; + switch (parent->layout) { + case L_VERT: + lenient_strcat(buffer, "V["); + break; + case L_HORIZ: + lenient_strcat(buffer, "H["); + break; + case L_TABBED: + lenient_strcat(buffer, "T["); + break; + case L_STACKED: + lenient_strcat(buffer, "S["); + break; + case L_FLOATING: + lenient_strcat(buffer, "F["); + break; + case L_NONE: + lenient_strcat(buffer, "D["); + break; } - for (int i = 0; i < parent->children->length; ++i) { if (i != 0) { - len += 1; - if (buffer) { - strcat(buffer, " "); - } + ++len; + lenient_strcat(buffer, " "); } struct sway_container *child = parent->children->items[i]; const char *identifier = NULL; @@ -819,48 +814,39 @@ static size_t concatenate_child_titles(struct sway_container *parent, identifier = view_get_app_id(child->sway_view); } } else { - identifier = child->name; + identifier = child->formatted_title; } if (identifier) { len += strlen(identifier); - if (buffer) { - strcat(buffer, identifier); - } + lenient_strcat(buffer, identifier); } else { len += 6; - if (buffer) { - strcat(buffer, "(null)"); - } + lenient_strcat(buffer, "(null)"); } } - - len += 1; - if (buffer) { - strcat(buffer, "]"); - } + ++len; + lenient_strcat(buffer, "]"); return len; } -void container_notify_child_title_changed(struct sway_container *container) { +void container_notify_subtree_changed(struct sway_container *container) { if (!container || container->type != C_CONTAINER) { return; } - if (container->formatted_title) { - free(container->formatted_title); - } + free(container->formatted_title); + container->formatted_title = NULL; - size_t len = concatenate_child_titles(container, NULL); + size_t len = get_tree_representation(container, NULL); char *buffer = calloc(len + 1, sizeof(char)); if (!sway_assert(buffer, "Unable to allocate title string")) { return; } - concatenate_child_titles(container, buffer); + get_tree_representation(container, buffer); - container->name = buffer; container->formatted_title = buffer; container_calculate_title_height(container); container_update_title_textures(container); - container_notify_child_title_changed(container->parent); + container_notify_subtree_changed(container->parent); } size_t container_titlebar_height() { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 91759f7bc..edc24deb3 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -149,7 +149,7 @@ struct sway_container *container_remove_child(struct sway_container *child) { } } child->parent = NULL; - container_notify_child_title_changed(parent); + container_notify_subtree_changed(parent); return parent; } @@ -184,8 +184,8 @@ void container_move_to(struct sway_container *container, container_sort_workspaces(new_parent); seat_set_focus(seat, new_parent); } - container_notify_child_title_changed(old_parent); - container_notify_child_title_changed(new_parent); + container_notify_subtree_changed(old_parent); + container_notify_subtree_changed(new_parent); if (old_parent) { if (old_parent->type == C_OUTPUT) { arrange_output(old_parent); @@ -497,8 +497,8 @@ void container_move(struct sway_container *container, } } - container_notify_child_title_changed(old_parent); - container_notify_child_title_changed(container->parent); + container_notify_subtree_changed(old_parent); + container_notify_subtree_changed(container->parent); if (old_parent) { seat_set_focus(config->handler_context.seat, old_parent); @@ -847,7 +847,7 @@ struct sway_container *container_split(struct sway_container *child, container_add_child(cont, child); } - container_notify_child_title_changed(cont); + container_notify_subtree_changed(cont); return cont; } diff --git a/sway/tree/view.c b/sway/tree/view.c index 071578188..2f718a73b 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -17,6 +17,7 @@ #include "sway/tree/workspace.h" #include "sway/config.h" #include "pango.h" +#include "stringop.h" void view_init(struct sway_view *view, enum sway_view_type type, const struct sway_view_impl *impl) { @@ -470,7 +471,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { input_manager_set_focus(input_manager, cont); view_update_title(view, false); - container_notify_child_title_changed(view->swayc->parent); + container_notify_subtree_changed(view->swayc->parent); view_execute_criteria(view); container_damage_whole(cont); @@ -661,49 +662,35 @@ static size_t parse_title_format(struct sway_view *view, char *buffer) { char *format = view->title_format; char *next = strchr(format, '%'); while (next) { - if (buffer) { - // Copy everything up to the % - strncat(buffer, format, next - format); - } + // Copy everything up to the % + lenient_strncat(buffer, format, next - format); len += next - format; format = next; if (strncmp(next, "%title", 6) == 0) { - if (buffer && title) { - strcat(buffer, title); - } + lenient_strcat(buffer, title); len += title_len; format += 6; } else if (strncmp(next, "%class", 6) == 0) { - if (buffer && class) { - strcat(buffer, class); - } + lenient_strcat(buffer, class); len += class_len; format += 6; } else if (strncmp(next, "%instance", 9) == 0) { - if (buffer && instance) { - strcat(buffer, instance); - } + lenient_strcat(buffer, instance); len += instance_len; format += 9; } else if (strncmp(next, "%shell", 6) == 0) { - if (buffer) { - strcat(buffer, shell); - } + lenient_strcat(buffer, shell); len += shell_len; format += 6; } else { - if (buffer) { - strcat(buffer, "%"); - } + lenient_strcat(buffer, "%"); ++format; ++len; } next = strchr(format, '%'); } - if (buffer) { - strcat(buffer, format); - } + lenient_strcat(buffer, format); len += strlen(format); return len; @@ -759,7 +746,6 @@ void view_update_title(struct sway_view *view, bool force) { } container_calculate_title_height(view->swayc); container_update_title_textures(view->swayc); - container_notify_child_title_changed(view->swayc->parent); config_update_font_height(false); }