From 5b8b3baa6537d56de5a4c78dfd505a851da25aa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 24 Mar 2021 20:51:18 +0100 Subject: [PATCH 1/3] render: render_osd(): no need to pass width/height as parameters All uses of render_osd() passes buf->width/buf->height as width/height. Thus, we can simply remove the width/height parameters and have render_osd() use buf->width and buf->height directly. --- render.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/render.c b/render.c index d8e1a009..f250560a 100644 --- a/render.c +++ b/render.c @@ -1751,12 +1751,12 @@ render_osd(struct terminal *term, struct wl_surface *surf, struct wl_subsurface *sub_surf, struct buffer *buf, const wchar_t *text, uint32_t _fg, uint32_t _bg, - unsigned width, unsigned height, unsigned x, unsigned y) + unsigned x, unsigned y) { pixman_color_t bg = color_hex_to_pixman(_bg); pixman_image_fill_rectangles( PIXMAN_OP_SRC, buf->pix[0], &bg, 1, - &(pixman_rectangle16_t){0, 0, width, height}); + &(pixman_rectangle16_t){0, 0, buf->width, buf->height}); struct fcft_font *font = term->fonts[0]; pixman_color_t fg = color_hex_to_pixman(_fg); @@ -1782,12 +1782,12 @@ render_osd(struct terminal *term, quirk_weston_subsurface_desync_on(sub_surf); wl_surface_attach(surf, buf->wl_buf, 0, 0); - wl_surface_damage_buffer(surf, 0, 0, width, height); + wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height); wl_surface_set_buffer_scale(surf, term->scale); struct wl_region *region = wl_compositor_create_region(term->wl->compositor); if (region != NULL) { - wl_region_add(region, 0, 0, width, height); + wl_region_add(region, 0, 0, buf->width, buf->height); wl_surface_set_opaque_region(surf, region); wl_region_destroy(region); } @@ -1916,7 +1916,7 @@ render_scrollback_position(struct terminal *term) win->scrollback_indicator.sub, buf, text, term->colors.table[0], term->colors.table[8 + 4], - width, height, width - margin - wcslen(text) * term->cell_width, margin); + width - margin - wcslen(text) * term->cell_width, margin); } @@ -1949,7 +1949,7 @@ render_render_timer(struct terminal *term, struct timeval render_time) win->render_timer.sub, buf, text, term->colors.table[0], term->colors.table[8 + 1], - width, height, margin, margin); + margin, margin); } static void frame_callback( @@ -2670,8 +2670,8 @@ render_urls(struct terminal *term) ? term->conf->colors.jump_label.bg : term->colors.table[3]; - render_osd(term, surf, sub_surf, buf, label, - fg, bg, width, height, x_margin, y_margin); + render_osd( + term, surf, sub_surf, buf, label, fg, bg, x_margin, y_margin); } } From 1a0f13640e6f007cd08220dc54fed8b6dd8eec3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 24 Mar 2021 20:52:58 +0100 Subject: [PATCH 2/3] render: make sure surface buffer sizes are a multiple of the scaling factor The buffer attached to a surface with wl_surface_attach() must have a width and height that both are a multiple of the scale configured for that buffer: The new size of the surface is calculated based on the buffer size transformed by the inverse buffer_transform and the inverse buffer_scale. This means that at commit time the supplied buffer size must be an integer multiple of the buffer_scale. If that's not the case, an invalid_size error is sent. Due to a libwayland bug[^1], this is currently *not* being reported as an error. However, recent versions of Sway have started enforcing this, and is e.g. dropping (not rendering) sub-surfaces that does not adhere to this. [^1]: https://gitlab.freedesktop.org/wayland/wayland/-/issues/194 Closes #409 --- render.c | 52 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/render.c b/render.c index f250560a..b857e360 100644 --- a/render.c +++ b/render.c @@ -1409,6 +1409,9 @@ get_csd_data(const struct terminal *term, enum csd_surface surf_idx) static void csd_commit(struct terminal *term, struct wl_surface *surf, struct buffer *buf) { + xassert(buf->width % term->scale == 0); + xassert(buf->height % term->scale == 0); + wl_surface_attach(surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height); wl_surface_set_buffer_scale(surf, term->scale); @@ -1440,6 +1443,9 @@ render_csd_title(struct terminal *term) xassert(info.width > 0 && info.height > 0); + xassert(info.width % term->scale == 0); + xassert(info.height % term->scale == 0); + unsigned long cookie = shm_cookie_csd(term, CSD_SURF_TITLE); struct buffer *buf = shm_get_buffer( term->wl->shm, info.width, info.height, cookie, false, 1); @@ -1472,6 +1478,9 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx) if (info.width == 0 || info.height == 0) return; + xassert(info.width % term->scale == 0); + xassert(info.height % term->scale == 0); + unsigned long cookie = shm_cookie_csd(term, surf_idx); struct buffer *buf = shm_get_buffer( term->wl->shm, info.width, info.height, cookie, false, 1); @@ -1641,6 +1650,9 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx) if (info.width == 0 || info.height == 0) return; + xassert(info.width % term->scale == 0); + xassert(info.height % term->scale == 0); + unsigned long cookie = shm_cookie_csd(term, surf_idx); struct buffer *buf = shm_get_buffer( term->wl->shm, info.width, info.height, cookie, false, 1); @@ -1780,6 +1792,9 @@ render_osd(struct terminal *term, x += term->cell_width; } + xassert(buf->width % term->scale == 0); + xassert(buf->height % term->scale == 0); + quirk_weston_subsurface_desync_on(sub_surf); wl_surface_attach(surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height); @@ -1873,8 +1888,11 @@ render_scrollback_position(struct terminal *term) const int scale = term->scale; const int margin = 3 * scale; - const int width = 2 * margin + cell_count * term->cell_width; - const int height = 2 * margin + term->cell_height; + + const int width = + (2 * margin + cell_count * term->cell_width + scale - 1) / scale * scale; + const int height = + (2 * margin + term->cell_height + scale - 1) / scale * scale; unsigned long cookie = shm_cookie_scrollback_indicator(term); struct buffer *buf = shm_get_buffer( @@ -1929,10 +1947,13 @@ render_render_timer(struct terminal *term, struct timeval render_time) double usecs = render_time.tv_sec * 1000000 + render_time.tv_usec; swprintf(text, sizeof(text) / sizeof(text[0]), L"%.2f µs", usecs); + const int scale = term->scale; const int cell_count = wcslen(text); - const int margin = 3 * term->scale; - const int width = 2 * margin + cell_count * term->cell_width; - const int height = 2 * margin + term->cell_height; + const int margin = 3 * scale; + const int width = + (2 * margin + cell_count * term->cell_width + scale - 1) / scale * scale; + const int height = + (2 * margin + term->cell_height + scale - 1) / scale * scale; unsigned long cookie = shm_cookie_render_timer(term); struct buffer *buf = shm_get_buffer( @@ -2227,6 +2248,9 @@ grid_render(struct terminal *term) term->window->surface, 0, 0, INT32_MAX, INT32_MAX); } + xassert(buf->width % term->scale == 0); + xassert(buf->height % term->scale == 0); + wl_surface_attach(term->window->surface, buf->wl_buf, 0, 0); quirk_kde_damage_before_attach(term->window->surface); wl_surface_commit(term->window->surface); @@ -2298,10 +2322,10 @@ render_search_box(struct terminal *term) const size_t width = term->width - 2 * margin; const size_t visible_width = min( term->width - 2 * margin, - 2 * margin + wanted_visible_cells * term->cell_width); + (2 * margin + wanted_visible_cells * term->cell_width + scale - 1) / scale * scale); const size_t height = min( term->height - 2 * margin, - 2 * margin + 1 * term->cell_height); + (2 * margin + 1 * term->cell_height + scale - 1) / scale * scale); const size_t visible_cells = (visible_width - 2 * margin) / term->cell_width; size_t glyph_offset = term->render.search_glyph_offset; @@ -2527,6 +2551,9 @@ render_search_box(struct terminal *term) margin / scale, max(0, (int32_t)term->height - height - margin) / scale); + xassert(buf->width % scale == 0); + xassert(buf->height % scale == 0); + wl_surface_attach(term->window->search.surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(term->window->search.surf, 0, 0, width, height); wl_surface_set_buffer_scale(term->window->search.surf, scale); @@ -2634,10 +2661,13 @@ render_urls(struct terminal *term) size_t len = wcslen(label); int cols = wcswidth(label, len); - const int x_margin = 2 * term->scale; - const int y_margin = 1 * term->scale; - int width = 2 * x_margin + cols * term->cell_width; - int height = 2 * y_margin + term->cell_height; + const int scale = term->scale; + const int x_margin = 2 * scale; + const int y_margin = 1 * scale; + const int width = + (2 * x_margin + cols * term->cell_width + scale - 1) / scale * scale; + const int height = + (2 * y_margin + term->cell_height + scale - 1) / scale * scale; struct buffer *buf = shm_get_buffer( term->wl->shm, width, height, shm_cookie_url(url), false, 1); From a8de14c0bf3ddeaa65e098f20dfbdd4a41d76f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 25 Mar 2021 09:42:15 +0100 Subject: [PATCH 3/3] changelog: sub-surface sizes not a multiple of the scaling factor --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c7a6b1f..53f95872 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,10 @@ first having sent a `keyboard::enter` event (https://codeberg.org/dnkl/foot/issues/411). * Deadlock when rendering sixel images. +* URL labels, scrollback search box or scrollback position indicator + sometimes not showing up, caused by invalidly sized surface buffers + when output scaling was enabled + (https://codeberg.org/dnkl/foot/issues/409). ### Security