From 846271e8d3056ef3ecd3d2f4b7df6151e17c3c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 26 Jan 2025 09:28:54 +0100 Subject: [PATCH] render: resize: configure with only one dimension being zero The protocol states: If the width or height arguments are zero, it means the client should decide its own window dimension. This may happen when the compositor needs to configure the state of the surface but doesn't have any information about any previous or expected dimension. The wording is a bit ambiguous; does it mean we should set *both* width and height to values we choose, even if only one dimension is zero in the configure event? Or does it mean that we should choose the value for the dimension that is zero in the configure event? Regardless, it's pretty clear that it does *not* mean we should *only* choose width and height if *both* dimensions are zero in the configure event. This is foot's behavior before this patch, meaning if only one of them is zero, foot assumed the compositor wanted us to set the width (or height) to zero... Change this, so that we now choose value for the "missing" dimension, but do use the compositor provided value for the other dimension. Closes #1925 Relevant issues: * https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/155 * https://github.com/YaLTeR/niri/issues/1050 --- CHANGELOG.md | 8 ++++++++ render.c | 57 ++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 50 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a249ef2d..97becf79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,6 +68,14 @@ ### Changed + +* Do not try to set a zero width, or height, if the compositor sends a + _configure_ event with only one dimension being zero + ([#1925][1925]). + +[1925]: https://codeberg.org/dnkl/foot/issues/1925 + + ### Deprecated ### Removed ### Fixed diff --git a/render.c b/render.c index b1791a90..0cca0643 100644 --- a/render.c +++ b/render.c @@ -4295,17 +4295,24 @@ send_dimensions_to_client(struct terminal *term) static void set_size_from_grid(struct terminal *term, int *width, int *height, int cols, int rows) { + int new_width, new_height; + /* Nominal grid dimensions */ - *width = cols * term->cell_width; - *height = rows * term->cell_height; + new_width = cols * term->cell_width; + new_height = rows * term->cell_height; /* Include any configured padding */ - *width += 2 * term->conf->pad_x * term->scale; - *height += 2 * term->conf->pad_y * term->scale; + new_width += 2 * term->conf->pad_x * term->scale; + new_height += 2 * term->conf->pad_y * term->scale; /* Round to multiples of scale */ - *width = round(term->scale * round(*width / term->scale)); - *height = round(term->scale * round(*height / term->scale)); + new_width = round(term->scale * round(new_width / term->scale)); + new_height = round(term->scale * round(new_height / term->scale)); + + if (width != NULL) + *width = new_width; + if (height != NULL) + *height = new_height; } /* Move to terminal.c? */ @@ -4336,34 +4343,54 @@ render_resize(struct terminal *term, int width, int height, uint8_t opts) set_size_from_grid(term, &width, &height, term->cols, term->rows); } - if (width == 0 && height == 0) { - /* The compositor is letting us choose the size */ - if (term->stashed_width != 0 && term->stashed_height != 0) { + if (width == 0) { + /* The compositor is letting us choose the width */ + if (term->stashed_width != 0) { /* If a default size is requested, prefer the "last used" size */ width = term->stashed_width; - height = term->stashed_height; } else { /* Otherwise, use a user-configured size */ switch (term->conf->size.type) { case CONF_SIZE_PX: width = term->conf->size.width; + + if (wayl_win_csd_borders_visible(term->window)) + width -= 2 * term->conf->csd.border_width_visible; + + width *= scale; + break; + + case CONF_SIZE_CELLS: + set_size_from_grid(term, &width, NULL, + term->conf->size.width, term->conf->size.height); + break; + } + } + } + + if (height == 0) { + /* The compositor is letting us choose the height */ + if (term->stashed_height != 0) { + /* If a default size is requested, prefer the "last used" size */ + height = term->stashed_height; + } else { + /* Otherwise, use a user-configured size */ + switch (term->conf->size.type) { + case CONF_SIZE_PX: height = term->conf->size.height; /* Take CSDs into account */ if (wayl_win_csd_titlebar_visible(term->window)) height -= term->conf->csd.title_height; - if (wayl_win_csd_borders_visible(term->window)) { + if (wayl_win_csd_borders_visible(term->window)) height -= 2 * term->conf->csd.border_width_visible; - width -= 2 * term->conf->csd.border_width_visible; - } - width *= scale; height *= scale; break; case CONF_SIZE_CELLS: - set_size_from_grid(term, &width, &height, + set_size_from_grid(term, NULL, &height, term->conf->size.width, term->conf->size.height); break; }