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
This commit is contained in:
Ryan Dwyer 2018-05-25 21:07:59 +10:00
parent 3c77f066a5
commit db38b9bbf3
7 changed files with 79 additions and 83 deletions

View file

@ -55,6 +55,20 @@ void strip_quotes(char *str) {
*end = '\0'; *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. // strcmp that also handles null pointers.
int lenient_strcmp(char *a, char *b) { int lenient_strcmp(char *a, char *b) {
if (a == b) { if (a == b) {

View file

@ -1,5 +1,6 @@
#ifndef _SWAY_STRINGOP_H #ifndef _SWAY_STRINGOP_H
#define _SWAY_STRINGOP_H #define _SWAY_STRINGOP_H
#include <stdlib.h>
#include "list.h" #include "list.h"
#if !HAVE_DECL_SETENV #if !HAVE_DECL_SETENV
@ -14,6 +15,10 @@ char *strip_whitespace(char *str);
char *strip_comments(char *str); char *strip_comments(char *str);
void strip_quotes(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. // strcmp that also handles null pointers.
int lenient_strcmp(char *a, char *b); int lenient_strcmp(char *a, char *b);

View file

@ -216,7 +216,11 @@ void container_update_title_textures(struct sway_container *container);
*/ */
void container_calculate_title_height(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. * Return the height of a regular title bar.

View file

@ -52,6 +52,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
} }
} }
container_notify_subtree_changed(parent);
arrange_children_of(parent); arrange_children_of(parent);
return cmd_results_new(CMD_SUCCESS, NULL, NULL); return cmd_results_new(CMD_SUCCESS, NULL, NULL);

View file

@ -21,6 +21,7 @@
#include "sway/tree/view.h" #include "sway/tree/view.h"
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
#include "log.h" #include "log.h"
#include "stringop.h"
static list_t *bfs_queue; 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. * Calculate and return the length of the tree representation.
* An example concatenated title is: V[Terminal, Firefox] * An example tree representation is: V[Terminal, Firefox]
* If buffer is not NULL, also populate the buffer with the concatenated title. * If buffer is not NULL, also populate the buffer with the representation.
*/ */
static size_t concatenate_child_titles(struct sway_container *parent, static size_t get_tree_representation(struct sway_container *parent, char *buffer) {
char *buffer) { size_t len = 2;
size_t len = 2; // V[ switch (parent->layout) {
if (buffer) { case L_VERT:
switch (parent->layout) { lenient_strcat(buffer, "V[");
case L_VERT: break;
strcpy(buffer, "V["); case L_HORIZ:
break; lenient_strcat(buffer, "H[");
case L_HORIZ: break;
strcpy(buffer, "H["); case L_TABBED:
break; lenient_strcat(buffer, "T[");
case L_TABBED: break;
strcpy(buffer, "T["); case L_STACKED:
break; lenient_strcat(buffer, "S[");
case L_STACKED: break;
strcpy(buffer, "S["); case L_FLOATING:
break; lenient_strcat(buffer, "F[");
case L_FLOATING: break;
strcpy(buffer, "F["); case L_NONE:
break; lenient_strcat(buffer, "D[");
case L_NONE: break;
strcpy(buffer, "D[");
break;
}
} }
for (int i = 0; i < parent->children->length; ++i) { for (int i = 0; i < parent->children->length; ++i) {
if (i != 0) { if (i != 0) {
len += 1; ++len;
if (buffer) { lenient_strcat(buffer, " ");
strcat(buffer, " ");
}
} }
struct sway_container *child = parent->children->items[i]; struct sway_container *child = parent->children->items[i];
const char *identifier = NULL; 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); identifier = view_get_app_id(child->sway_view);
} }
} else { } else {
identifier = child->name; identifier = child->formatted_title;
} }
if (identifier) { if (identifier) {
len += strlen(identifier); len += strlen(identifier);
if (buffer) { lenient_strcat(buffer, identifier);
strcat(buffer, identifier);
}
} else { } else {
len += 6; len += 6;
if (buffer) { lenient_strcat(buffer, "(null)");
strcat(buffer, "(null)");
}
} }
} }
++len;
len += 1; lenient_strcat(buffer, "]");
if (buffer) {
strcat(buffer, "]");
}
return len; 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) { if (!container || container->type != C_CONTAINER) {
return; 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)); char *buffer = calloc(len + 1, sizeof(char));
if (!sway_assert(buffer, "Unable to allocate title string")) { if (!sway_assert(buffer, "Unable to allocate title string")) {
return; return;
} }
concatenate_child_titles(container, buffer); get_tree_representation(container, buffer);
container->name = buffer;
container->formatted_title = buffer; container->formatted_title = buffer;
container_calculate_title_height(container); container_calculate_title_height(container);
container_update_title_textures(container); container_update_title_textures(container);
container_notify_child_title_changed(container->parent); container_notify_subtree_changed(container->parent);
} }
size_t container_titlebar_height() { size_t container_titlebar_height() {

View file

@ -149,7 +149,7 @@ struct sway_container *container_remove_child(struct sway_container *child) {
} }
} }
child->parent = NULL; child->parent = NULL;
container_notify_child_title_changed(parent); container_notify_subtree_changed(parent);
return parent; return parent;
} }
@ -184,8 +184,8 @@ void container_move_to(struct sway_container *container,
container_sort_workspaces(new_parent); container_sort_workspaces(new_parent);
seat_set_focus(seat, new_parent); seat_set_focus(seat, new_parent);
} }
container_notify_child_title_changed(old_parent); container_notify_subtree_changed(old_parent);
container_notify_child_title_changed(new_parent); container_notify_subtree_changed(new_parent);
if (old_parent) { if (old_parent) {
if (old_parent->type == C_OUTPUT) { if (old_parent->type == C_OUTPUT) {
arrange_output(old_parent); arrange_output(old_parent);
@ -497,8 +497,8 @@ void container_move(struct sway_container *container,
} }
} }
container_notify_child_title_changed(old_parent); container_notify_subtree_changed(old_parent);
container_notify_child_title_changed(container->parent); container_notify_subtree_changed(container->parent);
if (old_parent) { if (old_parent) {
seat_set_focus(config->handler_context.seat, 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_add_child(cont, child);
} }
container_notify_child_title_changed(cont); container_notify_subtree_changed(cont);
return cont; return cont;
} }

View file

@ -17,6 +17,7 @@
#include "sway/tree/workspace.h" #include "sway/tree/workspace.h"
#include "sway/config.h" #include "sway/config.h"
#include "pango.h" #include "pango.h"
#include "stringop.h"
void view_init(struct sway_view *view, enum sway_view_type type, void view_init(struct sway_view *view, enum sway_view_type type,
const struct sway_view_impl *impl) { 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); input_manager_set_focus(input_manager, cont);
view_update_title(view, false); view_update_title(view, false);
container_notify_child_title_changed(view->swayc->parent); container_notify_subtree_changed(view->swayc->parent);
view_execute_criteria(view); view_execute_criteria(view);
container_damage_whole(cont); 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 *format = view->title_format;
char *next = strchr(format, '%'); char *next = strchr(format, '%');
while (next) { while (next) {
if (buffer) { // Copy everything up to the %
// Copy everything up to the % lenient_strncat(buffer, format, next - format);
strncat(buffer, format, next - format);
}
len += next - format; len += next - format;
format = next; format = next;
if (strncmp(next, "%title", 6) == 0) { if (strncmp(next, "%title", 6) == 0) {
if (buffer && title) { lenient_strcat(buffer, title);
strcat(buffer, title);
}
len += title_len; len += title_len;
format += 6; format += 6;
} else if (strncmp(next, "%class", 6) == 0) { } else if (strncmp(next, "%class", 6) == 0) {
if (buffer && class) { lenient_strcat(buffer, class);
strcat(buffer, class);
}
len += class_len; len += class_len;
format += 6; format += 6;
} else if (strncmp(next, "%instance", 9) == 0) { } else if (strncmp(next, "%instance", 9) == 0) {
if (buffer && instance) { lenient_strcat(buffer, instance);
strcat(buffer, instance);
}
len += instance_len; len += instance_len;
format += 9; format += 9;
} else if (strncmp(next, "%shell", 6) == 0) { } else if (strncmp(next, "%shell", 6) == 0) {
if (buffer) { lenient_strcat(buffer, shell);
strcat(buffer, shell);
}
len += shell_len; len += shell_len;
format += 6; format += 6;
} else { } else {
if (buffer) { lenient_strcat(buffer, "%");
strcat(buffer, "%");
}
++format; ++format;
++len; ++len;
} }
next = strchr(format, '%'); next = strchr(format, '%');
} }
if (buffer) { lenient_strcat(buffer, format);
strcat(buffer, format);
}
len += strlen(format); len += strlen(format);
return len; return len;
@ -759,7 +746,6 @@ void view_update_title(struct sway_view *view, bool force) {
} }
container_calculate_title_height(view->swayc); container_calculate_title_height(view->swayc);
container_update_title_textures(view->swayc); container_update_title_textures(view->swayc);
container_notify_child_title_changed(view->swayc->parent);
config_update_font_height(false); config_update_font_height(false);
} }