diff --git a/include/sway/config.h b/include/sway/config.h index 02ae3b63..345f26a0 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -304,7 +304,7 @@ struct sway_config { enum sway_container_layout default_orientation; enum sway_container_layout default_layout; char *font; - int font_height; + size_t font_height; // Flags bool focus_follows_mouse; @@ -461,7 +461,12 @@ struct bar_config *default_bar_config(void); void free_bar_config(struct bar_config *bar); -int get_font_text_height(char *font); +/** + * Updates the value of config->font_height based on the max title height + * reported by each container. If recalculate is true, the containers will + * recalculate their heights before reporting. + */ +void config_find_font_height(bool recalculate); /* Global config singleton. */ extern struct sway_config *config; diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index b508f310..b07af72c 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -89,6 +89,7 @@ struct sway_container { struct wlr_texture *title_focused_inactive; struct wlr_texture *title_unfocused; struct wlr_texture *title_urgent; + size_t title_height; struct { struct wl_signal destroy; @@ -198,4 +199,12 @@ struct sway_container *container_flatten(struct sway_container *container); void container_update_title_textures(struct sway_container *container); +/** + * Calculate the container's title_height property. + */ +void container_calculate_title_height(struct sway_container *container); + +void container_update_title(struct sway_container *container, + const char *new_title); + #endif diff --git a/sway/commands/font.c b/sway/commands/font.c index 96127055..38ad8880 100644 --- a/sway/commands/font.c +++ b/sway/commands/font.c @@ -2,6 +2,7 @@ #include #include "sway/commands.h" #include "sway/config.h" +#include "sway/tree/arrange.h" #include "log.h" #include "stringop.h" @@ -13,6 +14,9 @@ struct cmd_results *cmd_font(int argc, char **argv) { char *font = join_args(argv, argc); free(config->font); config->font = strdup(font); - config->font_height = get_font_text_height(font); + config_find_font_height(true); + if (!config->reading) { + arrange_root(); + } return cmd_results_new(CMD_SUCCESS, NULL, NULL); } diff --git a/sway/config.c b/sway/config.c index 60b62bbc..0ad9c3a2 100644 --- a/sway/config.c +++ b/sway/config.c @@ -132,17 +132,6 @@ static void destroy_removed_seats(struct sway_config *old_config, } } -int get_font_text_height(char *font) { - cairo_t *cairo = cairo_create(NULL); - int text_height; - get_text_size(cairo, font, NULL, &text_height, 1, false, - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz" - "!@#$%^&*([{|"); - cairo_destroy(cairo); - return text_height; -} - static void set_color(float dest[static 4], uint32_t color) { dest[0] = ((color >> 16) & 0xff) / 255.0; dest[1] = ((color >> 8) & 0xff) / 255.0; @@ -182,7 +171,7 @@ static void config_defaults(struct sway_config *config) { config->default_layout = L_NONE; config->default_orientation = L_NONE; if (!(config->font = strdup("monospace 10"))) goto cleanup; - config->font_height = get_font_text_height(config->font); + config->font_height = 0; // floating view config->floating_maximum_width = 0; @@ -740,3 +729,20 @@ int workspace_output_cmp_workspace(const void *a, const void *b) { const struct workspace_output *wsa = a, *wsb = b; return lenient_strcmp(wsa->workspace, wsb->workspace); } + +static void find_font_height_iterator(struct sway_container *container, + void *data) { + bool *recalculate = data; + if (*recalculate) { + container_calculate_title_height(container); + } + if (container->title_height > config->font_height) { + config->font_height = container->title_height; + } +} + +void config_find_font_height(bool recalculate) { + config->font_height = 0; + container_for_each_descendant_dfs(&root_container, + find_font_height_iterator, &recalculate); +} diff --git a/sway/tree/container.c b/sway/tree/container.c index b33985af..d19f13ae 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -348,7 +348,7 @@ struct sway_container *container_view_create(struct sway_container *sibling, swayc, title, sibling, sibling ? sibling->type : 0, sibling->name); // Setup values swayc->sway_view = sway_view; - swayc->name = title ? strdup(title) : NULL; + container_update_title(swayc, title); swayc->width = 0; swayc->height = 0; @@ -611,3 +611,54 @@ void container_update_title_textures(struct sway_container *container) { update_title_texture(container, &container->title_urgent, &config->border_colors.urgent); } + +void container_calculate_title_height(struct sway_container *container) { + if (!container->name) { + container->title_height = 0; + return; + } + cairo_t *cairo = cairo_create(NULL); + int height; + get_text_size(cairo, config->font, NULL, &height, 1, false, + "%s", container->name); + cairo_destroy(cairo); + container->title_height = height; +} + +static void container_notify_child_title_changed( + struct sway_container *container) { + if (!container || container->type != C_CONTAINER) { + return; + } + if (container->layout != L_TABBED && container->layout != L_STACKED) { + return; + } + if (container->name) { + free(container->name); + } + // TODO: iterate children and concatenate their titles + container->name = strdup(""); + container_calculate_title_height(container); + container_update_title_textures(container); + container_notify_child_title_changed(container->parent); +} + +void container_update_title(struct sway_container *container, + const char *new_title) { + if (container->name && strcmp(container->name, new_title) == 0) { + return; + } + if (container->name) { + free(container->name); + } + container->name = strdup(new_title); + container_calculate_title_height(container); + container_update_title_textures(container); + container_notify_child_title_changed(container->parent); + + size_t prev_max_height = config->font_height; + config_find_font_height(false); + if (config->font_height != prev_max_height) { + arrange_root(); + } +}