diff --git a/common/pango.c b/common/pango.c index dbc369dc..88932203 100644 --- a/common/pango.c +++ b/common/pango.c @@ -109,6 +109,24 @@ void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, free(buf); } +void get_text_metrics(const char *font, int *height, int *baseline) { + cairo_t *cairo = cairo_create(NULL); + PangoContext *pango = pango_cairo_create_context(cairo); + PangoFontDescription *description = pango_font_description_from_string(font); + PangoFontMetrics *metrics; + + // When passing NULL as a language, pango uses the current locale. + metrics = pango_context_get_metrics(pango, description, NULL); + + *baseline = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE; + *height = *baseline + pango_font_metrics_get_descent(metrics) / PANGO_SCALE; + + pango_font_metrics_unref(metrics); + pango_font_description_free(description); + g_object_unref(pango); + cairo_destroy(cairo); +} + void pango_printf(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...) { va_list args; diff --git a/include/pango.h b/include/pango.h index 75dbba27..7f41441b 100644 --- a/include/pango.h +++ b/include/pango.h @@ -17,6 +17,7 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font, const char *text, double scale, bool markup); void get_text_size(cairo_t *cairo, const char *font, int *width, int *height, int *baseline, double scale, bool markup, const char *fmt, ...); +void get_text_metrics(const char *font, int *height, int *baseline); void pango_printf(cairo_t *cairo, const char *font, double scale, bool markup, const char *fmt, ...); diff --git a/include/sway/config.h b/include/sway/config.h index b8327e9c..d6c29fe6 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -486,8 +486,8 @@ struct sway_config { enum sway_container_layout default_orientation; enum sway_container_layout default_layout; char *font; - size_t font_height; - size_t font_baseline; + int font_height; + int font_baseline; bool pango_markup; int titlebar_border_thickness; int titlebar_h_padding; @@ -696,14 +696,13 @@ void free_bar_binding(struct bar_binding *binding); void free_workspace_config(struct workspace_config *wsc); /** - * 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. - * + * Updates the value of config->font_height based on the metrics for title's + * font as reported by pango. + * * If the height has changed, all containers will be rearranged to take on the * new size. */ -void config_update_font_height(bool recalculate); +void config_update_font_height(void); /** * Convert bindsym into bindcode using the first configured layout. diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index 38ee68bd..97fa98c1 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -119,8 +119,6 @@ struct sway_container { struct wlr_texture *title_focused_inactive; struct wlr_texture *title_unfocused; struct wlr_texture *title_urgent; - size_t title_height; - size_t title_baseline; list_t *marks; // char * struct wlr_texture *marks_focused; @@ -183,11 +181,6 @@ 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); - size_t container_build_representation(enum sway_container_layout layout, list_t *children, char *buffer); diff --git a/sway/commands/font.c b/sway/commands/font.c index c54365b5..cea720f5 100644 --- a/sway/commands/font.c +++ b/sway/commands/font.c @@ -22,6 +22,6 @@ struct cmd_results *cmd_font(int argc, char **argv) { } free(font); - config_update_font_height(true); + config_update_font_height(); return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 3c994d54..09ccd9d4 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -48,7 +48,7 @@ static void do_reload(void *data) { } list_free_items_and_destroy(bar_ids); - config_update_font_height(true); + config_update_font_height(); root_for_each_container(rebuild_textures_iterator, NULL); arrange_root(); diff --git a/sway/commands/title_format.c b/sway/commands/title_format.c index 9d312470..8d907e76 100644 --- a/sway/commands/title_format.c +++ b/sway/commands/title_format.c @@ -23,6 +23,6 @@ struct cmd_results *cmd_title_format(int argc, char **argv) { } view->title_format = format; view_update_title(view, true); - config_update_font_height(true); + config_update_font_height(); return cmd_results_new(CMD_SUCCESS, NULL); } diff --git a/sway/config.c b/sway/config.c index fde386c7..1ddedc7e 100644 --- a/sway/config.c +++ b/sway/config.c @@ -991,31 +991,11 @@ int workspace_output_cmp_workspace(const void *a, const void *b) { return lenient_strcmp(wsa->workspace, wsb->workspace); } -static void find_font_height_iterator(struct sway_container *con, void *data) { - size_t amount_below_baseline = con->title_height - con->title_baseline; - size_t extended_height = config->font_baseline + amount_below_baseline; - if (extended_height > config->font_height) { - config->font_height = extended_height; - } -} - -static void find_baseline_iterator(struct sway_container *con, void *data) { - bool *recalculate = data; - if (*recalculate) { - container_calculate_title_height(con); - } - if (con->title_baseline > config->font_baseline) { - config->font_baseline = con->title_baseline; - } -} -void config_update_font_height(bool recalculate) { - size_t prev_max_height = config->font_height; - config->font_height = 0; - config->font_baseline = 0; +void config_update_font_height(void) { + int prev_max_height = config->font_height; - root_for_each_container(find_baseline_iterator, &recalculate); - root_for_each_container(find_font_height_iterator, NULL); + get_text_metrics(config->font, &config->font_height, &config->font_baseline); if (config->font_height != prev_max_height) { arrange_root(); diff --git a/sway/desktop/render.c b/sway/desktop/render.c index a5bd8a5f..d25df570 100644 --- a/sway/desktop/render.c +++ b/sway/desktop/render.c @@ -559,8 +559,7 @@ static void render_titlebar(struct sway_output *output, // The title texture might be shorter than the config->font_height, // in which case we need to pad it above and below. - int ob_padding_above = round((config->font_baseline - - con->title_baseline + titlebar_v_padding - + int ob_padding_above = round((titlebar_v_padding - titlebar_border_thickness) * output_scale); int ob_padding_below = ob_bg_height - ob_padding_above - texture_box.height; diff --git a/sway/tree/container.c b/sway/tree/container.c index 3b661046..00c40218 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -509,7 +509,8 @@ static void update_title_texture(struct sway_container *con, double scale = output->wlr_output->scale; int width = 0; - int height = con->title_height * scale; + int height = config->font_height * scale; + int baseline; // We must use a non-nil cairo_t for cairo_set_font_options to work. // Therefore, we cannot use cairo_create(NULL). @@ -527,7 +528,7 @@ static void update_title_texture(struct sway_container *con, to_cairo_subpixel_order(output->wlr_output->subpixel)); } cairo_set_font_options(c, fo); - get_text_size(c, config->font, &width, NULL, NULL, scale, + get_text_size(c, config->font, &width, NULL, &baseline, scale, config->pango_markup, "%s", con->formatted_title); cairo_surface_destroy(dummy_surface); cairo_destroy(c); @@ -536,6 +537,10 @@ static void update_title_texture(struct sway_container *con, return; } + if (height > config->font_height * scale) { + height = config->font_height * scale; + } + cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); cairo_t *cairo = cairo_create(surface); @@ -548,7 +553,7 @@ static void update_title_texture(struct sway_container *con, PangoContext *pango = pango_cairo_create_context(cairo); cairo_set_source_rgba(cairo, class->text[0], class->text[1], class->text[2], class->text[3]); - cairo_move_to(cairo, 0, 0); + cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); pango_printf(cairo, config->font, scale, config->pango_markup, "%s", con->formatted_title); @@ -577,21 +582,6 @@ void container_update_title_textures(struct sway_container *container) { container_damage_whole(container); } -void container_calculate_title_height(struct sway_container *container) { - if (!container->formatted_title) { - container->title_height = 0; - return; - } - cairo_t *cairo = cairo_create(NULL); - int height; - int baseline; - get_text_size(cairo, config->font, NULL, &height, &baseline, 1, - config->pango_markup, "%s", container->formatted_title); - cairo_destroy(cairo); - container->title_height = height; - container->title_baseline = baseline; -} - /** * Calculate and return the length of the tree representation. * An example tree representation is: V[Terminal, Firefox] @@ -657,7 +647,6 @@ void container_update_representation(struct sway_container *con) { } container_build_representation(con->pending.layout, con->pending.children, con->formatted_title); - container_calculate_title_height(con); container_update_title_textures(con); } if (con->pending.parent) { @@ -1628,10 +1617,11 @@ static void update_marks_texture(struct sway_container *con, double scale = output->wlr_output->scale; int width = 0; - int height = con->title_height * scale; + int height = config->font_height * scale; + int baseline; cairo_t *c = cairo_create(NULL); - get_text_size(c, config->font, &width, NULL, NULL, scale, false, + get_text_size(c, config->font, &width, NULL, &baseline, scale, false, "%s", buffer); cairo_destroy(c); @@ -1639,6 +1629,10 @@ static void update_marks_texture(struct sway_container *con, return; } + if (height > config->font_height) { + height = config->font_height; + } + cairo_surface_t *surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, width, height); cairo_t *cairo = cairo_create(surface); @@ -1649,7 +1643,7 @@ static void update_marks_texture(struct sway_container *con, cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); cairo_set_source_rgba(cairo, class->text[0], class->text[1], class->text[2], class->text[3]); - cairo_move_to(cairo, 0, 0); + cairo_move_to(cairo, 0, config->font_baseline * scale - baseline); pango_printf(cairo, config->font, scale, false, "%s", buffer); diff --git a/sway/tree/view.c b/sway/tree/view.c index fcdd06f7..3ab971f7 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1285,8 +1285,7 @@ void view_update_title(struct sway_view *view, bool force) { view->container->title = NULL; view->container->formatted_title = NULL; } - container_calculate_title_height(view->container); - config_update_font_height(false); + config_update_font_height(); // Update title after the global font height is updated container_update_title_textures(view->container);