From 1e6204e1ac3e153fc4eb95a78cb0710803c93130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Mar 2023 10:43:30 +0100 Subject: [PATCH 01/33] meson: generate bindings for wp-fractional-scale + wp-viewport --- meson.build | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/meson.build b/meson.build index 29951541..3bad7ab2 100644 --- a/meson.build +++ b/meson.build @@ -158,6 +158,11 @@ if wayland_protocols.version().version_compare('>=1.21') add_project_arguments('-DHAVE_XDG_ACTIVATION', language: 'c') wl_proto_xml += [wayland_protocols_datadir + '/staging/xdg-activation/xdg-activation-v1.xml'] endif +if wayland_protocols.version().version_compare('>=1.31') + add_project_arguments('-DHAVE_FRACTIONAL_SCALE', language: 'c') + wl_proto_xml += [wayland_protocols_datadir + '/stable/viewporter/viewporter.xml'] + wl_proto_xml += [wayland_protocols_datadir + '/staging/fractional-scale/fractional-scale-v1.xml'] +endif foreach prot : wl_proto_xml wl_proto_headers += custom_target( From a9ecf1449e731c2461ced75cc9c16247523aca47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 8 Mar 2023 10:44:03 +0100 Subject: [PATCH 02/33] wayland: plumbing for wp-fractional-scale * Bind the wp-viewporter and wp-fractional-scale-manager globals. * Create a viewport and fractional-scale when instantiating a window. * Add fractional-scale listener (that does nothing at the moment). * Destroy everything on teardown. --- wayland.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ wayland.h | 16 +++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/wayland.c b/wayland.c index 51161cf0..7aa48e71 100644 --- a/wayland.c +++ b/wayland.c @@ -1121,6 +1121,27 @@ handle_global(void *data, struct wl_registry *registry, } #endif +#if defined(HAVE_FRACTIONAL_SCALE) + else if (strcmp(interface, wp_viewporter_interface.name) == 0) { + const uint32_t required = 1; + if (!verify_iface_version(interface, version, required)) + return; + + wayl->viewporter = wl_registry_bind( + wayl->registry, name, &wp_viewporter_interface, required); + } + + else if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) { + const uint32_t required = 1; + if (!verify_iface_version(interface, version, required)) + return; + + wayl->fractional_scale_manager = wl_registry_bind( + wayl->registry, name, + &wp_fractional_scale_manager_v1_interface, required); + } +#endif + #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED else if (strcmp(interface, zwp_text_input_manager_v3_interface.name) == 0) { const uint32_t required = 1; @@ -1435,6 +1456,12 @@ wayl_destroy(struct wayland *wayl) zwp_text_input_manager_v3_destroy(wayl->text_input_manager); #endif +#if defined(HAVE_FRACTIONAL_SCALE) + if (wayl->fractional_scale_manager != NULL) + wp_fractional_scale_manager_v1_destroy(wayl->fractional_scale_manager); + if (wayl->viewporter != NULL) + wp_viewporter_destroy(wayl->viewporter); +#endif #if defined(HAVE_XDG_ACTIVATION) if (wayl->xdg_activation != NULL) xdg_activation_v1_destroy(wayl->xdg_activation); @@ -1469,6 +1496,21 @@ wayl_destroy(struct wayland *wayl) free(wayl); } +#if defined(HAVE_FRACTIONAL_SCALE) +static void fractional_scale_preferred_scale( + void *data, struct wp_fractional_scale_v1 *wp_fractional_scale_v1, + uint32_t scale) +{ + struct wl_window *win = data; + win->scale = (float)scale / 120.; + LOG_DBG("fractional scale: %.3f", win->scale); +} + +static const struct wp_fractional_scale_v1_listener fractional_scale_listener = { + .preferred_scale = &fractional_scale_preferred_scale, +}; +#endif + struct wl_window * wayl_win_init(struct terminal *term, const char *token) { @@ -1499,6 +1541,19 @@ wayl_win_init(struct terminal *term, const char *token) wl_surface_add_listener(win->surface, &surface_listener, win); +#if defined(HAVE_FRACTIONAL_SCALE) + if (wayl->fractional_scale_manager != NULL && wayl->viewporter != NULL) { + LOG_ERR("LDKJFLDF"); + win->viewport = wp_viewporter_get_viewport(wayl->viewporter, win->surface); + + win->fractional_scale = + wp_fractional_scale_manager_v1_get_fractional_scale( + wayl->fractional_scale_manager, win->surface); + wp_fractional_scale_v1_add_listener( + win->fractional_scale, &fractional_scale_listener, win); + } +#endif + win->xdg_surface = xdg_wm_base_get_xdg_surface(wayl->shell, win->surface); xdg_surface_add_listener(win->xdg_surface, &xdg_surface_listener, win); @@ -1652,6 +1707,12 @@ wayl_win_destroy(struct wl_window *win) tll_remove(win->xdg_tokens, it); } +#endif +#if defined(HAVE_FRACTIONAL_SCALE) + if (win->fractional_scale != NULL) + wp_fractional_scale_v1_destroy(win->fractional_scale); + if (win->viewport != NULL) + wp_viewport_destroy(win->viewport); #endif if (win->frame_callback != NULL) wl_callback_destroy(win->frame_callback); diff --git a/wayland.h b/wayland.h index 0d627052..20edcb68 100644 --- a/wayland.h +++ b/wayland.h @@ -20,6 +20,11 @@ #include #endif +#if defined(HAVE_FRACTIONAL_SCALE) + #include + #include +#endif + #include #include @@ -326,9 +331,15 @@ struct wl_window { #if defined(HAVE_XDG_ACTIVATION) tll(struct xdg_activation_token_context *) xdg_tokens; bool urgency_token_is_pending; +#endif +#if defined(HAVE_FRACTIONAL_SCALE) + struct wp_viewport *viewport; + struct wp_fractional_scale_v1 *fractional_scale; #endif bool unmapped; + float scale; + struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; enum csd_mode csd_mode; @@ -414,6 +425,11 @@ struct wayland { struct zwp_text_input_manager_v3 *text_input_manager; #endif +#if defined(HAVE_FRACTIONAL_SCALE) + struct wp_viewporter *viewporter; + struct wp_fractional_scale_manager_v1 *fractional_scale_manager; +#endif + bool have_argb8888; tll(struct monitor) monitors; /* All available outputs */ tll(struct seat) seats; From c1f374cc8dab121388669cee6df3e2d1c483d77f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:21:51 +0200 Subject: [PATCH 03/33] =?UTF-8?q?term:=20convert=20=E2=80=98scale=E2=80=99?= =?UTF-8?q?=20to=20a=20float?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- csi.c | 20 ++++++++++++-------- render.c | 24 ++++++++++++------------ terminal.h | 2 +- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/csi.c b/csi.c index ef1a28f2..153a1099 100644 --- a/csi.c +++ b/csi.c @@ -1206,8 +1206,10 @@ csi_dispatch(struct terminal *term, uint8_t final) if (width >= 0 && height >= 0) { char reply[64]; - size_t n = xsnprintf(reply, sizeof(reply), "\033[4;%d;%dt", - height / term->scale, width / term->scale); + size_t n = xsnprintf( + reply, sizeof(reply), "\033[4;%d;%dt", + (int)round(height / term->scale), + (int)(width / term->scale)); term_to_slave(term, reply, n); } break; @@ -1229,9 +1231,10 @@ csi_dispatch(struct terminal *term, uint8_t final) case 16: { /* report cell size in pixels */ char reply[64]; - size_t n = xsnprintf(reply, sizeof(reply), "\033[6;%d;%dt", - term->cell_height / term->scale, - term->cell_width / term->scale); + size_t n = xsnprintf( + reply, sizeof(reply), "\033[6;%d;%dt", + (int)round(term->cell_height / term->scale), + (int)round(term->cell_width / term->scale)); term_to_slave(term, reply, n); break; } @@ -1247,9 +1250,10 @@ csi_dispatch(struct terminal *term, uint8_t final) case 19: { /* report screen size in chars */ tll_foreach(term->window->on_outputs, it) { char reply[64]; - size_t n = xsnprintf(reply, sizeof(reply), "\033[9;%d;%dt", - it->item->dim.px_real.height / term->cell_height / term->scale, - it->item->dim.px_real.width / term->cell_width / term->scale); + size_t n = xsnprintf( + reply, sizeof(reply), "\033[9;%d;%dt", + (int)round(it->item->dim.px_real.height / term->cell_height / term->scale), + (int)round(it->item->dim.px_real.width / term->cell_width / term->scale)); term_to_slave(term, reply, n); break; } diff --git a/render.c b/render.c index 1858467d..f5438e42 100644 --- a/render.c +++ b/render.c @@ -1830,8 +1830,8 @@ 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); + xassert(buf->width % (int)term->scale == 0); + xassert(buf->height % (int)term->scale == 0); wl_surface_attach(surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height); @@ -1926,8 +1926,8 @@ render_osd(struct terminal *term, pixman_image_unref(src); pixman_image_set_clip_region32(buf->pix[0], NULL); - xassert(buf->width % term->scale == 0); - xassert(buf->height % term->scale == 0); + xassert(buf->width % (int)term->scale == 0); + xassert(buf->height % (int)term->scale == 0); quirk_weston_subsurface_desync_on(sub_surf); wl_surface_attach(surf, buf->wl_buf, 0, 0); @@ -1955,8 +1955,8 @@ render_csd_title(struct terminal *term, const struct csd_data *info, if (info->width == 0 || info->height == 0) return; - xassert(info->width % term->scale == 0); - xassert(info->height % term->scale == 0); + xassert(info->width % (int)term->scale == 0); + xassert(info->height % (int)term->scale == 0); uint32_t bg = term->conf->csd.color.title_set ? term->conf->csd.color.title @@ -2000,8 +2000,8 @@ 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); + xassert(info->width % (int)term->scale == 0); + xassert(info->height % (int)term->scale == 0); { pixman_color_t color = color_hex_to_pixman_with_alpha(0, 0); @@ -2289,8 +2289,8 @@ 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); + xassert(info->width % (int)term->scale == 0); + xassert(info->height % (int)term->scale == 0); uint32_t _color; uint16_t alpha = 0xffff; @@ -3067,8 +3067,8 @@ 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); + xassert(buf->width % (int)term->scale == 0); + xassert(buf->height % (int)term->scale == 0); wl_surface_attach(term->window->surface, buf->wl_buf, 0, 0); wl_surface_commit(term->window->surface); diff --git a/terminal.h b/terminal.h index e239e2af..220070e1 100644 --- a/terminal.h +++ b/terminal.h @@ -454,7 +454,7 @@ struct terminal { int fd; } blink; - int scale; + float scale; int width; /* pixels */ int height; /* pixels */ int stashed_width; From 6e2a47287aa5160134a8bb75f562af5c85f3aaf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:23:53 +0200 Subject: [PATCH 04/33] wayland: pointer.scale: convert to float --- wayland.c | 4 ++-- wayland.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/wayland.c b/wayland.c index 7aa48e71..b5bca9ba 100644 --- a/wayland.c +++ b/wayland.c @@ -1733,7 +1733,7 @@ wayl_win_destroy(struct wl_window *win) } bool -wayl_reload_xcursor_theme(struct seat *seat, int new_scale) +wayl_reload_xcursor_theme(struct seat *seat, float new_scale) { if (seat->pointer.theme != NULL && seat->pointer.scale == new_scale) { /* We already have a theme loaded, and the scale hasn't changed */ @@ -1766,7 +1766,7 @@ wayl_reload_xcursor_theme(struct seat *seat, int new_scale) const char *xcursor_theme = getenv("XCURSOR_THEME"); - LOG_INFO("cursor theme: %s, size: %d, scale: %d", + LOG_INFO("cursor theme: %s, size: %d, scale: %.2f", xcursor_theme ? xcursor_theme : "(null)", xcursor_size, new_scale); diff --git a/wayland.h b/wayland.h index 20edcb68..a5316837 100644 --- a/wayland.h +++ b/wayland.h @@ -135,7 +135,7 @@ struct seat { struct wl_surface *surface; struct wl_cursor_theme *theme; struct wl_cursor *cursor; - int scale; + float scale; bool hidden; const char *xcursor; @@ -442,7 +442,7 @@ struct wayland *wayl_init( bool presentation_timings); void wayl_destroy(struct wayland *wayl); -bool wayl_reload_xcursor_theme(struct seat *seat, int new_scale); +bool wayl_reload_xcursor_theme(struct seat *seat, float new_scale); void wayl_flush(struct wayland *wayl); void wayl_roundtrip(struct wayland *wayl); From 44743b5635aeee2d9cbb2bae33d5dcbc374be8da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:27:16 +0200 Subject: [PATCH 05/33] render: draw_unfocused_block(): round scale, instead of truncating --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index f5438e42..e62e000d 100644 --- a/render.c +++ b/render.c @@ -311,7 +311,7 @@ static void draw_unfocused_block(const struct terminal *term, pixman_image_t *pix, const pixman_color_t *color, int x, int y, int cell_cols) { - const int scale = term->scale; + const int scale = round(term->scale); const int width = min(min(scale, term->cell_width), term->cell_height); pixman_image_fill_rectangles( From b65612479135da9bf888fcd037c86519940e17b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:27:37 +0200 Subject: [PATCH 06/33] render: csd_border: round scaled border width, instead of truncating --- render.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/render.c b/render.c index e62e000d..f87ef093 100644 --- a/render.c +++ b/render.c @@ -2012,9 +2012,9 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx, * The “visible” border. */ - int scale = term->scale; - int bwidth = term->conf->csd.border_width * scale; - int vwidth = term->conf->csd.border_width_visible * scale; /* Visible size */ + float scale = term->scale; + int bwidth = round(term->conf->csd.border_width * scale); + int vwidth = round(term->conf->csd.border_width_visible * scale); /* Visible size */ xassert(bwidth >= vwidth); @@ -2067,7 +2067,6 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx, uint16_t alpha = _color >> 24 | (_color >> 24 << 8); pixman_color_t color = color_hex_to_pixman_with_alpha(_color, alpha); - pixman_image_fill_rectangles( PIXMAN_OP_SRC, buf->pix[0], &color, 1, &(pixman_rectangle16_t){x, y, w, h}); From cf280e6655da63dd6d2c2e146ec1ff8e71235779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:35:02 +0200 Subject: [PATCH 07/33] render: render_timer(): round scaling factor --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index f87ef093..51f4f1e8 100644 --- a/render.c +++ b/render.c @@ -2568,7 +2568,7 @@ render_render_timer(struct terminal *term, struct timespec render_time) char32_t text[256]; mbstoc32(text, usecs_str, ALEN(text)); - const int scale = term->scale; + const int scale = round(term->scale); const int cell_count = c32len(text); const int margin = 3 * scale; const int width = From 30c8d3e652db1cff7138e5e916cdaf2c9b6026a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:35:19 +0200 Subject: [PATCH 08/33] render: search_box(): round scaling factor --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index 51f4f1e8..34648d53 100644 --- a/render.c +++ b/render.c @@ -3132,7 +3132,7 @@ render_search_box(struct terminal *term) const size_t wanted_visible_cells = max(20, total_cells); xassert(term->scale >= 1); - const int scale = term->scale; + const int scale = round(term->scale); const size_t margin = 3 * scale; From d8f64d1047415d1446dad893167d1a756ffa9a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:35:29 +0200 Subject: [PATCH 09/33] render: urls(): round scaling factor --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index 34648d53..80025d5e 100644 --- a/render.c +++ b/render.c @@ -3422,7 +3422,7 @@ render_urls(struct terminal *term) struct wl_window *win = term->window; xassert(tll_length(win->urls) > 0); - const int scale = term->scale; + const int scale = round(term->scale); const int x_margin = 2 * scale; const int y_margin = 1 * scale; From 2bb7b28837aac939dad61b7ca58a0dcef08399e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:37:31 +0200 Subject: [PATCH 10/33] =?UTF-8?q?render:=20xcursor=5Fupdate():=20convert?= =?UTF-8?q?=20local=20=E2=80=98scale=E2=80=99=20variable=20to=20float?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index 80025d5e..25249218 100644 --- a/render.c +++ b/render.c @@ -4276,7 +4276,7 @@ render_xcursor_update(struct seat *seat) xassert(seat->pointer.cursor != NULL); - const int scale = seat->pointer.scale; + const float scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; wl_surface_attach( From 424d0450840bc3db018457787fcdf93db101b265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:39:34 +0200 Subject: [PATCH 11/33] =?UTF-8?q?term:=20reload=5Ffonts():=20=E2=80=98scal?= =?UTF-8?q?e=E2=80=99=20is=20not=20a=20float?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- terminal.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/terminal.c b/terminal.c index 815dc2d4..43ba157b 100644 --- a/terminal.c +++ b/terminal.c @@ -1000,14 +1000,14 @@ reload_fonts(struct terminal *term) bool use_px_size = term->font_sizes[i][j].px_size > 0; char size[64]; - const int scale = term->font_is_sized_by_dpi ? 1 : term->scale; + const float scale = term->font_is_sized_by_dpi ? 1. : term->scale; if (use_px_size) snprintf(size, sizeof(size), ":pixelsize=%d", - term->font_sizes[i][j].px_size * scale); + (int)round(term->font_sizes[i][j].px_size * scale)); else snprintf(size, sizeof(size), ":size=%.2f", - term->font_sizes[i][j].pt_size * (double)scale); + term->font_sizes[i][j].pt_size * scale); size_t len = strlen(font->pattern) + strlen(size) + 1; names[i][j] = xmalloc(len); @@ -1232,7 +1232,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .reverse_wrap = true, .auto_margin = true, .window_title_stack = tll_init(), - .scale = 1, + .scale = 1., .flash = {.fd = flash_fd}, .blink = {.fd = -1}, .vt = { From 29a14632d369c6a9d2ceea70e75f17dc47ab23ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 14:39:49 +0200 Subject: [PATCH 12/33] =?UTF-8?q?wayland:=20csd=5Freload=5Ffont():=20?= =?UTF-8?q?=E2=80=98scale=E2=80=99=20is=20now=20a=20float?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wayland.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/wayland.c b/wayland.c index b5bca9ba..575d2e83 100644 --- a/wayland.c +++ b/wayland.c @@ -32,12 +32,12 @@ #include "xmalloc.h" static void -csd_reload_font(struct wl_window *win, int old_scale) +csd_reload_font(struct wl_window *win, float old_scale) { struct terminal *term = win->term; const struct config *conf = term->conf; - const int scale = term->scale; + const float scale = term->scale; bool enable_csd = win->csd_mode == CSD_YES && !win->is_fullscreen; if (!enable_csd) @@ -52,10 +52,10 @@ csd_reload_font(struct wl_window *win, int old_scale) patterns[i] = conf->csd.font.arr[i].pattern; char pixelsize[32]; - snprintf(pixelsize, sizeof(pixelsize), - "pixelsize=%u", conf->csd.title_height * scale * 1 / 2); + snprintf(pixelsize, sizeof(pixelsize), "pixelsize=%u", + (int)round(conf->csd.title_height * scale * 1 / 2)); - LOG_DBG("loading CSD font \"%s:%s\" (old-scale=%d, scale=%d)", + LOG_DBG("loading CSD font \"%s:%s\" (old-scale=%.2f, scale=%.2f)", patterns[0], pixelsize, old_scale, scale); win->csd.font = fcft_from_name(conf->csd.font.count, patterns, pixelsize); @@ -79,7 +79,7 @@ csd_instantiate(struct wl_window *win) xassert(ret); } - csd_reload_font(win, -1); + csd_reload_font(win, -1.); } static void @@ -334,7 +334,7 @@ update_term_for_output_change(struct terminal *term) if (tll_length(term->window->on_outputs) == 0) return; - int old_scale = term->scale; + float old_scale = term->scale; render_resize(term, term->width / term->scale, term->height / term->scale); term_font_dpi_changed(term, old_scale); From 913ae94cf99cb4a171ea69e6340b804a0e8c6a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 15:01:33 +0200 Subject: [PATCH 13/33] wayland: add wayl_fractional_scaling() Returns true if fractional scaling is available. --- wayland.c | 10 ++++++++++ wayland.h | 2 ++ 2 files changed, 12 insertions(+) diff --git a/wayland.c b/wayland.c index 575d2e83..e01a3a50 100644 --- a/wayland.c +++ b/wayland.c @@ -2048,3 +2048,13 @@ wayl_get_activation_token( return true; } #endif + +bool +wayl_fractional_scaling(const struct wayland *wayl) +{ +#if defined(HAVE_FRACTIONAL_SCALE) + return wayl->fractional_scale_manager != NULL; +#else + return false; +#endif +} diff --git a/wayland.h b/wayland.h index a5316837..756da8d2 100644 --- a/wayland.h +++ b/wayland.h @@ -469,3 +469,5 @@ bool wayl_get_activation_token( struct wayland *wayl, struct seat *seat, uint32_t serial, struct wl_window *win, activation_token_cb_t cb, void *cb_data); #endif + +bool wayl_fractional_scaling(const struct wayland *wayl); From 4bd62b10058c626cecb5eb15c9c44aee58bf547a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 22 Jun 2023 15:01:59 +0200 Subject: [PATCH 14/33] =?UTF-8?q?render:=20maybe=5Fresize():=20convert=20l?= =?UTF-8?q?ocal=20variable=20=E2=80=98scale=E2=80=99=20to=20float?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- render.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/render.c b/render.c index 25249218..3c2e6f18 100644 --- a/render.c +++ b/render.c @@ -3868,13 +3868,13 @@ maybe_resize(struct terminal *term, int width, int height, bool force) if (term->cell_width == 0 && term->cell_height == 0) return false; - int scale = -1; + float scale = -1; tll_foreach(term->window->on_outputs, it) { if (it->item->scale > scale) scale = it->item->scale; } - if (scale < 0) { + if (scale < 0.) { /* Haven't 'entered' an output yet? */ scale = term->scale; } @@ -3922,13 +3922,18 @@ maybe_resize(struct terminal *term, int width, int height, bool force) * Ensure we can scale to logical size, and back to * pixels without truncating. */ - if (width % scale) - width += scale - width % scale; - if (height % scale) - height += scale - height % scale; + if (wayl_fractional_scaling(term->wl)) { + xassert((int)round(scale) == (int)scale); - xassert(width % scale == 0); - xassert(height % scale == 0); + int iscale = scale; + if (width % iscale) + width += iscale - width % iscale; + if (height % iscale) + height += iscale - height % iscale; + + xassert(width % iscale == 0); + xassert(height % iscale == 0); + } break; } } From 0a5073f5703e89cfa4219d5b532cb134f9def6d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 15:51:04 +0200 Subject: [PATCH 15/33] wayland: add wayl_surface_scale(), and wayl_win_scale() These functions scale a surface+buffer. For now, only using the legacy scaling method (wl_surface_set_buffer_scale()). --- render.c | 47 +++++++++++++---------------------------------- wayland.c | 44 ++++++++++++++++++++++++++++++++++---------- wayland.h | 7 +++++-- 3 files changed, 52 insertions(+), 46 deletions(-) diff --git a/render.c b/render.c index 3c2e6f18..5663c45a 100644 --- a/render.c +++ b/render.c @@ -1691,8 +1691,8 @@ render_overlay(struct terminal *term) &(pixman_rectangle16_t){0, 0, term->width, term->height}); quirk_weston_subsurface_desync_on(overlay->sub); + wayl_surface_scale(term->wl, overlay->surf, term->scale); wl_subsurface_set_position(overlay->sub, 0, 0); - wl_surface_set_buffer_scale(overlay->surf, term->scale); wl_surface_attach(overlay->surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer( @@ -1830,12 +1830,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 % (int)term->scale == 0); - xassert(buf->height % (int)term->scale == 0); - + wayl_surface_scale(term->wl, surf, term->scale); 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); wl_surface_commit(surf); } @@ -1926,13 +1923,10 @@ render_osd(struct terminal *term, pixman_image_unref(src); pixman_image_set_clip_region32(buf->pix[0], NULL); - xassert(buf->width % (int)term->scale == 0); - xassert(buf->height % (int)term->scale == 0); - quirk_weston_subsurface_desync_on(sub_surf); + wayl_surface_scale(term->wl, surf, term->scale); 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); struct wl_region *region = wl_compositor_create_region(term->wl->compositor); if (region != NULL) { @@ -1955,9 +1949,6 @@ render_csd_title(struct terminal *term, const struct csd_data *info, if (info->width == 0 || info->height == 0) return; - xassert(info->width % (int)term->scale == 0); - xassert(info->height % (int)term->scale == 0); - uint32_t bg = term->conf->csd.color.title_set ? term->conf->csd.color.title : 0xffu << 24 | term->conf->colors.fg; @@ -2000,9 +1991,6 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx, if (info->width == 0 || info->height == 0) return; - xassert(info->width % (int)term->scale == 0); - xassert(info->height % (int)term->scale == 0); - { pixman_color_t color = color_hex_to_pixman_with_alpha(0, 0); render_csd_part(term, surf, buf, info->width, info->height, &color); @@ -2288,9 +2276,6 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx, if (info->width == 0 || info->height == 0) return; - xassert(info->width % (int)term->scale == 0); - xassert(info->height % (int)term->scale == 0); - uint32_t _color; uint16_t alpha = 0xffff; bool is_active = false; @@ -3032,7 +3017,7 @@ grid_render(struct terminal *term) term->window->frame_callback = wl_surface_frame(term->window->surface); wl_callback_add_listener(term->window->frame_callback, &frame_listener, term); - wl_surface_set_buffer_scale(term->window->surface, term->scale); + wayl_win_scale(term->window); if (term->wl->presentation != NULL && term->conf->presentation_timings) { struct timespec commit_time; @@ -3066,9 +3051,6 @@ grid_render(struct terminal *term) term->window->surface, 0, 0, INT32_MAX, INT32_MAX); } - xassert(buf->width % (int)term->scale == 0); - xassert(buf->height % (int)term->scale == 0); - wl_surface_attach(term->window->surface, buf->wl_buf, 0, 0); wl_surface_commit(term->window->surface); } @@ -3132,17 +3114,17 @@ render_search_box(struct terminal *term) const size_t wanted_visible_cells = max(20, total_cells); xassert(term->scale >= 1); - const int scale = round(term->scale); + const int rounded_scale = round(term->scale); - const size_t margin = 3 * scale; + const size_t margin = 3 * rounded_scale; 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 + scale - 1) / scale * scale); + (2 * margin + wanted_visible_cells * term->cell_width + rounded_scale - 1) / rounded_scale * rounded_scale); const size_t height = min( term->height - 2 * margin, - (2 * margin + 1 * term->cell_height + scale - 1) / scale * scale); + (2 * margin + 1 * term->cell_height + rounded_scale - 1) / rounded_scale * rounded_scale); const size_t visible_cells = (visible_width - 2 * margin) / term->cell_width; size_t glyph_offset = term->render.search_glyph_offset; @@ -3389,15 +3371,12 @@ render_search_box(struct terminal *term) /* TODO: this is only necessary on a window resize */ wl_subsurface_set_position( term->window->search.sub, - margin / scale, - max(0, (int32_t)term->height - height - margin) / scale); - - xassert(buf->width % scale == 0); - xassert(buf->height % scale == 0); + margin / term->scale, + max(0, (int32_t)term->height - height - margin) / term->scale); + wayl_surface_scale(term->wl, term->window->search.surf, term->scale); 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); struct wl_region *region = wl_compositor_create_region(term->wl->compositor); if (region != NULL) { @@ -4284,6 +4263,8 @@ render_xcursor_update(struct seat *seat) const float scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; + wayl_surface_scale(seat->wayl, seat->pointer.surface, scale); + wl_surface_attach( seat->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0); @@ -4295,8 +4276,6 @@ render_xcursor_update(struct seat *seat) wl_surface_damage_buffer( seat->pointer.surface, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_set_buffer_scale(seat->pointer.surface, scale); - xassert(seat->pointer.xcursor_callback == NULL); seat->pointer.xcursor_callback = wl_surface_frame(seat->pointer.surface); wl_callback_add_listener(seat->pointer.xcursor_callback, &xcursor_listener, seat); diff --git a/wayland.c b/wayland.c index e01a3a50..5aa10966 100644 --- a/wayland.c +++ b/wayland.c @@ -1850,6 +1850,40 @@ wayl_roundtrip(struct wayland *wayl) wayl_flush(wayl); } + +bool +wayl_fractional_scaling(const struct wayland *wayl) +{ +#if defined(HAVE_FRACTIONAL_SCALE) + return wayl->fractional_scale_manager != NULL; +#else + return false; +#endif +} + +void +wayl_surface_scale(const struct wayland *wayl, struct wl_surface *surf, + float scale) +{ + LOG_WARN("scaling by a factor of %.2f (legacy)", scale); + + if (wayl_fractional_scaling(wayl)) { + BUG("not yet implemented"); + } else { + wl_surface_set_buffer_scale(surf, (int)scale); + } +} + +void +wayl_win_scale(struct wl_window *win) +{ + const struct terminal *term = win->term; + const struct wayland *wayl = term->wl; + const float scale = term->scale; + + wayl_surface_scale(wayl, win->surface, scale); +} + void wayl_win_alpha_changed(struct wl_window *win) { @@ -2048,13 +2082,3 @@ wayl_get_activation_token( return true; } #endif - -bool -wayl_fractional_scaling(const struct wayland *wayl) -{ -#if defined(HAVE_FRACTIONAL_SCALE) - return wayl->fractional_scale_manager != NULL; -#else - return false; -#endif -} diff --git a/wayland.h b/wayland.h index 756da8d2..06150328 100644 --- a/wayland.h +++ b/wayland.h @@ -447,9 +447,14 @@ bool wayl_reload_xcursor_theme(struct seat *seat, float new_scale); void wayl_flush(struct wayland *wayl); void wayl_roundtrip(struct wayland *wayl); +bool wayl_fractional_scaling(const struct wayland *wayl); +void wayl_surface_scale( + const struct wayland *wayl, struct wl_surface *surf, float scale); + struct wl_window *wayl_win_init(struct terminal *term, const char *token); void wayl_win_destroy(struct wl_window *win); +void wayl_win_scale(struct wl_window *win); void wayl_win_alpha_changed(struct wl_window *win); bool wayl_win_set_urgent(struct wl_window *win); @@ -469,5 +474,3 @@ bool wayl_get_activation_token( struct wayland *wayl, struct seat *seat, uint32_t serial, struct wl_window *win, activation_token_cb_t cb, void *cb_data); #endif - -bool wayl_fractional_scaling(const struct wayland *wayl); From c5d533ec71aafe1c842189a7e662f7a7696c56a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 15:55:40 +0200 Subject: [PATCH 16/33] wayland: add viewport object to sub-surface struct --- wayland.c | 27 +++++++++++++++++++++++++-- wayland.h | 3 +++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/wayland.c b/wayland.c index 5aa10966..9a3d11e8 100644 --- a/wayland.c +++ b/wayland.c @@ -1543,7 +1543,6 @@ wayl_win_init(struct terminal *term, const char *token) #if defined(HAVE_FRACTIONAL_SCALE) if (wayl->fractional_scale_manager != NULL && wayl->viewporter != NULL) { - LOG_ERR("LDKJFLDF"); win->viewport = wp_viewporter_get_viewport(wayl->viewporter, win->surface); win->fractional_scale = @@ -1965,17 +1964,33 @@ wayl_win_subsurface_new_with_custom_parent( struct wl_surface *main_surface = wl_compositor_create_surface(wayl->compositor); - if (main_surface == NULL) + if (main_surface == NULL) { + LOG_ERR("failed to instantiate surface for sub-surface"); return false; + } struct wl_subsurface *sub = wl_subcompositor_get_subsurface( wayl->sub_compositor, main_surface, parent); if (sub == NULL) { + LOG_ERR("failed to instantiate sub-surface"); wl_surface_destroy(main_surface); return false; } +#if defined(HAVE_FRACTIONAL_SCALE) + struct wp_viewport *viewport = NULL; + if (wayl->fractional_scale_manager != NULL && wayl->viewporter != NULL) { + viewport = wp_viewporter_get_viewport(wayl->viewporter, main_surface); + if (viewport == NULL) { + LOG_ERR("failed to instantiate viewport for sub-surface"); + wl_subsurface_destroy(sub); + wl_surface_destroy(main_surface); + return false; + } + } +#endif + wl_surface_set_user_data(main_surface, win); wl_subsurface_set_sync(sub); @@ -1989,6 +2004,9 @@ wayl_win_subsurface_new_with_custom_parent( surf->surf = main_surface; surf->sub = sub; +#if defined(HAVE_FRACTIONAL_SCALE) + surf->viewport = viewport; +#endif return true; } @@ -2005,6 +2023,11 @@ wayl_win_subsurface_destroy(struct wl_surf_subsurf *surf) { if (surf == NULL) return; + +#if defined(HAVE_FRACTIONAL_SCALE) + if (surf->viewport != NULL) + wp_viewport_destroy(surf->viewport); +#endif if (surf->sub != NULL) wl_subsurface_destroy(surf->sub); if (surf->surf != NULL) diff --git a/wayland.h b/wayland.h index 06150328..bb9bf77f 100644 --- a/wayland.h +++ b/wayland.h @@ -297,6 +297,9 @@ struct monitor { struct wl_surf_subsurf { struct wl_surface *surf; struct wl_subsurface *sub; +#if defined(HAVE_FRACTIONAL_SCALE) + struct wp_viewport *viewport; +#endif }; struct wl_url { From ba46a039aca734bb284c22ba5d5bddf5407e3848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 16:10:40 +0200 Subject: [PATCH 17/33] wayland: refactor: wrap wl_surface pointers in a wayl_surface struct And add a viewport object to accompany the surface (to be used when scaling the surface). Also rename the wl_surf_subsurf struct to wayl_sub_surface, and add a wayl_surface object to it, rather than a plain wl_surface pointer (to also get the viewport pointer). --- quirks.c | 2 +- render.c | 100 +++++++++++++++++++++--------------------- terminal.c | 18 ++++---- wayland.c | 125 ++++++++++++++++++++++++++++------------------------- wayland.h | 43 +++++++++--------- 5 files changed, 149 insertions(+), 139 deletions(-) diff --git a/quirks.c b/quirks.c index bf9bc7fb..9769f1ff 100644 --- a/quirks.c +++ b/quirks.c @@ -89,5 +89,5 @@ quirk_sway_subsurface_unmap(struct terminal *term) if (!is_sway()) return; - wl_surface_damage_buffer(term->window->surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_damage_buffer(term->window->surface.surf, 0, 0, INT32_MAX, INT32_MAX); } diff --git a/render.c b/render.c index 5663c45a..5ebd69eb 100644 --- a/render.c +++ b/render.c @@ -905,21 +905,21 @@ render_margin(struct terminal *term, struct buffer *buf, if (apply_damage) { /* Top */ wl_surface_damage_buffer( - term->window->surface, 0, 0, term->width, term->margins.top); + term->window->surface.surf, 0, 0, term->width, term->margins.top); /* Bottom */ wl_surface_damage_buffer( - term->window->surface, 0, bmargin, term->width, term->margins.bottom); + term->window->surface.surf, 0, bmargin, term->width, term->margins.bottom); /* Left */ wl_surface_damage_buffer( - term->window->surface, + term->window->surface.surf, 0, term->margins.top + start_line * term->cell_height, term->margins.left, line_count * term->cell_height); /* Right */ wl_surface_damage_buffer( - term->window->surface, + term->window->surface.surf, rmargin, term->margins.top + start_line * term->cell_height, term->margins.right, line_count * term->cell_height); } @@ -1027,7 +1027,7 @@ grid_render_scroll(struct terminal *term, struct buffer *buf, #endif wl_surface_damage_buffer( - term->window->surface, term->margins.left, dst_y, + term->window->surface.surf, term->margins.left, dst_y, term->width - term->margins.left - term->margins.right, height); /* @@ -1104,7 +1104,7 @@ grid_render_scroll_reverse(struct terminal *term, struct buffer *buf, #endif wl_surface_damage_buffer( - term->window->surface, term->margins.left, dst_y, + term->window->surface.surf, term->margins.left, dst_y, term->width - term->margins.left - term->margins.right, height); /* @@ -1153,7 +1153,7 @@ render_sixel_chunk(struct terminal *term, pixman_image_t *pix, const struct sixe x, y, width, height); - wl_surface_damage_buffer(term->window->surface, x, y, width, height); + wl_surface_damage_buffer(term->window->surface.surf, x, y, width, height); } static void @@ -1480,7 +1480,7 @@ render_ime_preedit_for_seat(struct terminal *term, struct seat *seat, free(real_cells); wl_surface_damage_buffer( - term->window->surface, + term->window->surface.surf, term->margins.left, term->margins.top + row_idx * term->cell_height, term->width - term->margins.left - term->margins.right, @@ -1502,7 +1502,7 @@ render_ime_preedit(struct terminal *term, struct buffer *buf) static void render_overlay(struct terminal *term) { - struct wl_surf_subsurf *overlay = &term->window->overlay; + struct wayl_sub_surface *overlay = &term->window->overlay; bool unicode_mode_active = false; /* Check if unicode mode is active on at least one seat focusing @@ -1523,8 +1523,8 @@ render_overlay(struct terminal *term) if (likely(style == OVERLAY_NONE)) { if (term->render.last_overlay_style != OVERLAY_NONE) { /* Unmap overlay sub-surface */ - wl_surface_attach(overlay->surf, NULL, 0, 0); - wl_surface_commit(overlay->surf); + wl_surface_attach(overlay->surface.surf, NULL, 0, 0); + wl_surface_commit(overlay->surface.surf); term->render.last_overlay_style = OVERLAY_NONE; term->render.last_overlay_buf = NULL; @@ -1691,17 +1691,17 @@ render_overlay(struct terminal *term) &(pixman_rectangle16_t){0, 0, term->width, term->height}); quirk_weston_subsurface_desync_on(overlay->sub); - wayl_surface_scale(term->wl, overlay->surf, term->scale); + wayl_surface_scale(term->wl, overlay->surface.surf, term->scale); wl_subsurface_set_position(overlay->sub, 0, 0); - wl_surface_attach(overlay->surf, buf->wl_buf, 0, 0); + wl_surface_attach(overlay->surface.surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer( - overlay->surf, + overlay->surface.surf, damage_bounds.x1, damage_bounds.y1, damage_bounds.x2 - damage_bounds.x1, damage_bounds.y2 - damage_bounds.y1); - wl_surface_commit(overlay->surf); + wl_surface_commit(overlay->surface.surf); quirk_weston_subsurface_desync_off(overlay->sub); buf->age = 0; @@ -1945,7 +1945,7 @@ render_csd_title(struct terminal *term, const struct csd_data *info, { xassert(term->window->csd_mode == CSD_YES); - struct wl_surf_subsurf *surf = &term->window->csd.surface[CSD_SURF_TITLE]; + struct wayl_sub_surface *surf = &term->window->csd.surface[CSD_SURF_TITLE]; if (info->width == 0 || info->height == 0) return; @@ -1971,11 +1971,11 @@ render_csd_title(struct terminal *term, const struct csd_data *info, const int margin = M != NULL ? M->advance.x : win->csd.font->max_advance.x; - render_osd(term, surf->surf, surf->sub, win->csd.font, + render_osd(term, surf->surface.surf, surf->sub, win->csd.font, buf, title_text, fg, bg, margin, (buf->height - win->csd.font->height) / 2); - csd_commit(term, surf->surf, buf); + csd_commit(term, surf->surface.surf, buf); free(_title_text); } @@ -1986,7 +1986,7 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx, xassert(term->window->csd_mode == CSD_YES); xassert(surf_idx >= CSD_SURF_LEFT && surf_idx <= CSD_SURF_BOTTOM); - struct wl_surface *surf = term->window->csd.surface[surf_idx].surf; + struct wl_surface *surf = term->window->csd.surface[surf_idx].surface.surf; if (info->width == 0 || info->height == 0) return; @@ -2271,7 +2271,7 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx, xassert(term->window->csd_mode == CSD_YES); xassert(surf_idx >= CSD_SURF_MINIMIZE && surf_idx <= CSD_SURF_CLOSE); - struct wl_surface *surf = term->window->csd.surface[surf_idx].surf; + struct wl_surface *surf = term->window->csd.surface[surf_idx].surface.surf; if (info->width == 0 || info->height == 0) return; @@ -2358,7 +2358,7 @@ render_csd(struct terminal *term) const int width = infos[i].width; const int height = infos[i].height; - struct wl_surface *surf = term->window->csd.surface[i].surf; + struct wl_surface *surf = term->window->csd.surface[i].surface.surf; struct wl_subsurface *sub = term->window->csd.surface[i].sub; xassert(surf != NULL); @@ -2397,7 +2397,7 @@ render_scrollback_position(struct terminal *term) struct wl_window *win = term->window; if (term->grid->view == term->grid->offset) { - if (win->scrollback_indicator.surf != NULL) { + if (win->scrollback_indicator.surface.surf != NULL) { wayl_win_subsurface_destroy(&win->scrollback_indicator); /* Work around Sway bug - unmapping a sub-surface does not damage @@ -2407,7 +2407,7 @@ render_scrollback_position(struct terminal *term) return; } - if (win->scrollback_indicator.surf == NULL) { + if (win->scrollback_indicator.surface.surf == NULL) { if (!wayl_win_subsurface_new( win, &win->scrollback_indicator, false)) { @@ -2416,7 +2416,7 @@ render_scrollback_position(struct terminal *term) } } - xassert(win->scrollback_indicator.surf != NULL); + xassert(win->scrollback_indicator.surface.surf != NULL); xassert(win->scrollback_indicator.sub != NULL); /* Find absolute row number of the scrollback start */ @@ -2514,8 +2514,8 @@ render_scrollback_position(struct terminal *term) const int y = (term->margins.top + surf_top) / scale * scale; if (y + height > term->height) { - wl_surface_attach(win->scrollback_indicator.surf, NULL, 0, 0); - wl_surface_commit(win->scrollback_indicator.surf); + wl_surface_attach(win->scrollback_indicator.surface.surf, NULL, 0, 0); + wl_surface_commit(win->scrollback_indicator.surface.surf); return; } @@ -2534,7 +2534,7 @@ render_scrollback_position(struct terminal *term) render_osd( term, - win->scrollback_indicator.surf, + win->scrollback_indicator.surface.surf, win->scrollback_indicator.sub, term->fonts[0], buf, text, fg, 0xffu << 24 | bg, @@ -2571,7 +2571,7 @@ render_render_timer(struct terminal *term, struct timespec render_time) render_osd( term, - win->render_timer.surf, + win->render_timer.surface.surf, win->render_timer.sub, term->fonts[0], buf, text, term->colors.table[0], 0xffu << 24 | term->colors.table[8 + 1], @@ -2919,7 +2919,7 @@ grid_render(struct terminal *term) int height = (r - first_dirty_row) * term->cell_height; wl_surface_damage_buffer( - term->window->surface, x, y, width, height); + term->window->surface.surf, x, y, width, height); pixman_region32_union_rect( &buf->dirty, &buf->dirty, 0, y, buf->width, height); } @@ -2947,7 +2947,7 @@ grid_render(struct terminal *term) int width = term->width - term->margins.left - term->margins.right; int height = (term->rows - first_dirty_row) * term->cell_height; - wl_surface_damage_buffer(term->window->surface, x, y, width, height); + wl_surface_damage_buffer(term->window->surface.surf, x, y, width, height); pixman_region32_union_rect(&buf->dirty, &buf->dirty, 0, y, buf->width, height); } @@ -3014,7 +3014,7 @@ grid_render(struct terminal *term) xassert(term->grid->view >= 0 && term->grid->view < term->grid->num_rows); xassert(term->window->frame_callback == NULL); - term->window->frame_callback = wl_surface_frame(term->window->surface); + term->window->frame_callback = wl_surface_frame(term->window->surface.surf); wl_callback_add_listener(term->window->frame_callback, &frame_listener, term); wayl_win_scale(term->window); @@ -3024,7 +3024,7 @@ grid_render(struct terminal *term) clock_gettime(term->wl->presentation_clock_id, &commit_time); struct wp_presentation_feedback *feedback = wp_presentation_feedback( - term->wl->presentation, term->window->surface); + term->wl->presentation, term->window->surface.surf); if (feedback == NULL) { LOG_WARN("failed to create presentation feedback"); @@ -3048,11 +3048,11 @@ grid_render(struct terminal *term) if (term->conf->tweak.damage_whole_window) { wl_surface_damage_buffer( - term->window->surface, 0, 0, INT32_MAX, INT32_MAX); + term->window->surface.surf, 0, 0, INT32_MAX, INT32_MAX); } - wl_surface_attach(term->window->surface, buf->wl_buf, 0, 0); - wl_surface_commit(term->window->surface); + wl_surface_attach(term->window->surface.surf, buf->wl_buf, 0, 0); + wl_surface_commit(term->window->surface.surf); } static void @@ -3374,18 +3374,18 @@ render_search_box(struct terminal *term) margin / term->scale, max(0, (int32_t)term->height - height - margin) / term->scale); - wayl_surface_scale(term->wl, term->window->search.surf, term->scale); - wl_surface_attach(term->window->search.surf, buf->wl_buf, 0, 0); - wl_surface_damage_buffer(term->window->search.surf, 0, 0, width, height); + wayl_surface_scale(term->wl, term->window->search.surface.surf, term->scale); + wl_surface_attach(term->window->search.surface.surf, buf->wl_buf, 0, 0); + wl_surface_damage_buffer(term->window->search.surface.surf, 0, 0, width, height); struct wl_region *region = wl_compositor_create_region(term->wl->compositor); if (region != NULL) { wl_region_add(region, width - visible_width, 0, visible_width, height); - wl_surface_set_opaque_region(term->window->search.surf, region); + wl_surface_set_opaque_region(term->window->search.surface.surf, region); wl_region_destroy(region); } - wl_surface_commit(term->window->search.surf); + wl_surface_commit(term->window->search.surface.surf); quirk_weston_subsurface_desync_off(term->window->search.sub); #if defined(FOOT_IME_ENABLED) && FOOT_IME_ENABLED @@ -3466,7 +3466,7 @@ render_urls(struct terminal *term) continue; } - struct wl_surface *surf = it->item.surf.surf; + struct wl_surface *surf = it->item.surf.surface.surf; struct wl_subsurface *sub_surf = it->item.surf.sub; if (surf == NULL || sub_surf == NULL) @@ -3601,7 +3601,7 @@ render_urls(struct terminal *term) : term->colors.table[3]; for (size_t i = 0; i < render_count; i++) { - struct wl_surface *surf = info[i].url->surf.surf; + struct wl_surface *surf = info[i].url->surf.surface.surf; struct wl_subsurface *sub_surf = info[i].url->surf.sub; const char32_t *label = info[i].text; @@ -4253,8 +4253,8 @@ render_xcursor_update(struct seat *seat) if (seat->pointer.xcursor == XCURSOR_HIDDEN) { /* Hide cursor */ - wl_surface_attach(seat->pointer.surface, NULL, 0, 0); - wl_surface_commit(seat->pointer.surface); + wl_surface_attach(seat->pointer.surface.surf, NULL, 0, 0); + wl_surface_commit(seat->pointer.surface.surf); return; } @@ -4263,24 +4263,24 @@ render_xcursor_update(struct seat *seat) const float scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; - wayl_surface_scale(seat->wayl, seat->pointer.surface, scale); + wayl_surface_scale(seat->wayl, seat->pointer.surface.surf, scale); wl_surface_attach( - seat->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0); + seat->pointer.surface.surf, wl_cursor_image_get_buffer(image), 0, 0); wl_pointer_set_cursor( seat->wl_pointer, seat->pointer.serial, - seat->pointer.surface, + seat->pointer.surface.surf, image->hotspot_x / scale, image->hotspot_y / scale); wl_surface_damage_buffer( - seat->pointer.surface, 0, 0, INT32_MAX, INT32_MAX); + seat->pointer.surface.surf, 0, 0, INT32_MAX, INT32_MAX); xassert(seat->pointer.xcursor_callback == NULL); - seat->pointer.xcursor_callback = wl_surface_frame(seat->pointer.surface); + seat->pointer.xcursor_callback = wl_surface_frame(seat->pointer.surface.surf); wl_callback_add_listener(seat->pointer.xcursor_callback, &xcursor_listener, seat); - wl_surface_commit(seat->pointer.surface); + wl_surface_commit(seat->pointer.surface.surf); } static void diff --git a/terminal.c b/terminal.c index 43ba157b..825e1550 100644 --- a/terminal.c +++ b/terminal.c @@ -3589,23 +3589,23 @@ term_single_shift(struct terminal *term, enum charset_designator idx) enum term_surface term_surface_kind(const struct terminal *term, const struct wl_surface *surface) { - if (likely(surface == term->window->surface)) + if (likely(surface == term->window->surface.surf)) return TERM_SURF_GRID; - else if (surface == term->window->csd.surface[CSD_SURF_TITLE].surf) + else if (surface == term->window->csd.surface[CSD_SURF_TITLE].surface.surf) return TERM_SURF_TITLE; - else if (surface == term->window->csd.surface[CSD_SURF_LEFT].surf) + else if (surface == term->window->csd.surface[CSD_SURF_LEFT].surface.surf) return TERM_SURF_BORDER_LEFT; - else if (surface == term->window->csd.surface[CSD_SURF_RIGHT].surf) + else if (surface == term->window->csd.surface[CSD_SURF_RIGHT].surface.surf) return TERM_SURF_BORDER_RIGHT; - else if (surface == term->window->csd.surface[CSD_SURF_TOP].surf) + else if (surface == term->window->csd.surface[CSD_SURF_TOP].surface.surf) return TERM_SURF_BORDER_TOP; - else if (surface == term->window->csd.surface[CSD_SURF_BOTTOM].surf) + else if (surface == term->window->csd.surface[CSD_SURF_BOTTOM].surface.surf) return TERM_SURF_BORDER_BOTTOM; - else if (surface == term->window->csd.surface[CSD_SURF_MINIMIZE].surf) + else if (surface == term->window->csd.surface[CSD_SURF_MINIMIZE].surface.surf) return TERM_SURF_BUTTON_MINIMIZE; - else if (surface == term->window->csd.surface[CSD_SURF_MAXIMIZE].surf) + else if (surface == term->window->csd.surface[CSD_SURF_MAXIMIZE].surface.surf) return TERM_SURF_BUTTON_MAXIMIZE; - else if (surface == term->window->csd.surface[CSD_SURF_CLOSE].surf) + else if (surface == term->window->csd.surface[CSD_SURF_CLOSE].surface.surf) return TERM_SURF_BUTTON_CLOSE; else return TERM_SURF_NONE; diff --git a/wayland.c b/wayland.c index 9a3d11e8..3b6833c5 100644 --- a/wayland.c +++ b/wayland.c @@ -74,7 +74,7 @@ csd_instantiate(struct wl_window *win) for (size_t i = CSD_SURF_MINIMIZE; i < CSD_SURF_COUNT; i++) { bool ret = wayl_win_subsurface_new_with_custom_parent( - win, win->csd.surface[CSD_SURF_TITLE].surf, &win->csd.surface[i], + win, win->csd.surface[CSD_SURF_TITLE].surface.surf, &win->csd.surface[i], true); xassert(ret); } @@ -187,8 +187,12 @@ seat_destroy(struct seat *seat) if (seat->pointer.theme != NULL) wl_cursor_theme_destroy(seat->pointer.theme); - if (seat->pointer.surface != NULL) - wl_surface_destroy(seat->pointer.surface); + if (seat->pointer.surface.surf != NULL) + wl_surface_destroy(seat->pointer.surface.surf); +#if defined(HAVE_FRACTIONAL_SCALE) + if (seat->pointer.surface.viewport != NULL) + wp_viewport_destroy(seat->pointer.surface.viewport); +#endif if (seat->pointer.xcursor_callback != NULL) wl_callback_destroy(seat->pointer.xcursor_callback); @@ -288,10 +292,10 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, if (caps & WL_SEAT_CAPABILITY_POINTER) { if (seat->wl_pointer == NULL) { - xassert(seat->pointer.surface == NULL); - seat->pointer.surface = wl_compositor_create_surface(seat->wayl->compositor); + xassert(seat->pointer.surface.surf == NULL); + seat->pointer.surface.surf = wl_compositor_create_surface(seat->wayl->compositor); - if (seat->pointer.surface == NULL) { + if (seat->pointer.surface.surf == NULL) { LOG_ERR("%s: failed to create pointer surface", seat->name); return; } @@ -302,13 +306,13 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, } else { if (seat->wl_pointer != NULL) { wl_pointer_release(seat->wl_pointer); - wl_surface_destroy(seat->pointer.surface); + wl_surface_destroy(seat->pointer.surface.surf); if (seat->pointer.theme != NULL) wl_cursor_theme_destroy(seat->pointer.theme); seat->wl_pointer = NULL; - seat->pointer.surface = NULL; + seat->pointer.surface.surf = NULL; seat->pointer.theme = NULL; seat->pointer.cursor = NULL; } @@ -848,7 +852,7 @@ xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, * anytime soon. Some compositors require a commit in * combination with an ack - make them happy. */ - wl_surface_commit(win->surface); + wl_surface_commit(win->surface.surf); } if (wasnt_configured) @@ -1225,7 +1229,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) if (seat->wl_keyboard != NULL) keyboard_listener.leave( - seat, seat->wl_keyboard, -1, seat->kbd_focus->window->surface); + seat, seat->wl_keyboard, -1, seat->kbd_focus->window->surface.surf); } if (seat->mouse_focus != NULL) { @@ -1235,7 +1239,7 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) if (seat->wl_pointer != NULL) pointer_listener.leave( - seat, seat->wl_pointer, -1, seat->mouse_focus->window->surface); + seat, seat->wl_pointer, -1, seat->mouse_focus->window->surface.surf); } seat_destroy(seat); @@ -1531,29 +1535,29 @@ wayl_win_init(struct terminal *term, const char *token) win->wm_capabilities.maximize = true; win->wm_capabilities.minimize = true; - win->surface = wl_compositor_create_surface(wayl->compositor); - if (win->surface == NULL) { + win->surface.surf = wl_compositor_create_surface(wayl->compositor); + if (win->surface.surf == NULL) { LOG_ERR("failed to create wayland surface"); goto out; } wayl_win_alpha_changed(win); - wl_surface_add_listener(win->surface, &surface_listener, win); + wl_surface_add_listener(win->surface.surf, &surface_listener, win); #if defined(HAVE_FRACTIONAL_SCALE) if (wayl->fractional_scale_manager != NULL && wayl->viewporter != NULL) { - win->viewport = wp_viewporter_get_viewport(wayl->viewporter, win->surface); + win->surface.viewport = wp_viewporter_get_viewport(wayl->viewporter, win->surface.surf); win->fractional_scale = wp_fractional_scale_manager_v1_get_fractional_scale( - wayl->fractional_scale_manager, win->surface); + wayl->fractional_scale_manager, win->surface.surf); wp_fractional_scale_v1_add_listener( win->fractional_scale, &fractional_scale_listener, win); } #endif - win->xdg_surface = xdg_wm_base_get_xdg_surface(wayl->shell, win->surface); + win->xdg_surface = xdg_wm_base_get_xdg_surface(wayl->shell, win->surface.surf); xdg_surface_add_listener(win->xdg_surface, &xdg_surface_listener, win); win->xdg_toplevel = xdg_surface_get_toplevel(win->xdg_surface); @@ -1586,12 +1590,12 @@ wayl_win_init(struct terminal *term, const char *token) LOG_WARN("no decoration manager available - using CSDs unconditionally"); } - wl_surface_commit(win->surface); + wl_surface_commit(win->surface.surf); #if defined(HAVE_XDG_ACTIVATION) /* Complete XDG startup notification */ if (token) - xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface); + xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface.surf); #endif if (!wayl_win_subsurface_new(win, &win->overlay, false)) { @@ -1641,33 +1645,33 @@ wayl_win_destroy(struct wl_window *win) * nor mouse focus). */ - if (win->render_timer.surf != NULL) { - wl_surface_attach(win->render_timer.surf, NULL, 0, 0); - wl_surface_commit(win->render_timer.surf); + if (win->render_timer.surface.surf != NULL) { + wl_surface_attach(win->render_timer.surface.surf, NULL, 0, 0); + wl_surface_commit(win->render_timer.surface.surf); } - if (win->scrollback_indicator.surf != NULL) { - wl_surface_attach(win->scrollback_indicator.surf, NULL, 0, 0); - wl_surface_commit(win->scrollback_indicator.surf); + if (win->scrollback_indicator.surface.surf != NULL) { + wl_surface_attach(win->scrollback_indicator.surface.surf, NULL, 0, 0); + wl_surface_commit(win->scrollback_indicator.surface.surf); } /* Scrollback search */ - if (win->search.surf != NULL) { - wl_surface_attach(win->search.surf, NULL, 0, 0); - wl_surface_commit(win->search.surf); + if (win->search.surface.surf != NULL) { + wl_surface_attach(win->search.surface.surf, NULL, 0, 0); + wl_surface_commit(win->search.surface.surf); } /* URLs */ tll_foreach(win->urls, it) { - wl_surface_attach(it->item.surf.surf, NULL, 0, 0); - wl_surface_commit(it->item.surf.surf); + wl_surface_attach(it->item.surf.surface.surf, NULL, 0, 0); + wl_surface_commit(it->item.surf.surface.surf); } /* CSD */ for (size_t i = 0; i < ALEN(win->csd.surface); i++) { - if (win->csd.surface[i].surf != NULL) { - wl_surface_attach(win->csd.surface[i].surf, NULL, 0, 0); - wl_surface_commit(win->csd.surface[i].surf); + if (win->csd.surface[i].surface.surf != NULL) { + wl_surface_attach(win->csd.surface[i].surface.surf, NULL, 0, 0); + wl_surface_commit(win->csd.surface[i].surface.surf); } } @@ -1675,8 +1679,8 @@ wayl_win_destroy(struct wl_window *win) /* Main window */ win->unmapped = true; - wl_surface_attach(win->surface, NULL, 0, 0); - wl_surface_commit(win->surface); + wl_surface_attach(win->surface.surf, NULL, 0, 0); + wl_surface_commit(win->surface.surf); wayl_roundtrip(win->term->wl); tll_free(win->on_outputs); @@ -1710,8 +1714,8 @@ wayl_win_destroy(struct wl_window *win) #if defined(HAVE_FRACTIONAL_SCALE) if (win->fractional_scale != NULL) wp_fractional_scale_v1_destroy(win->fractional_scale); - if (win->viewport != NULL) - wp_viewport_destroy(win->viewport); + if (win->surface.viewport != NULL) + wp_viewport_destroy(win->surface.viewport); #endif if (win->frame_callback != NULL) wl_callback_destroy(win->frame_callback); @@ -1721,8 +1725,8 @@ wayl_win_destroy(struct wl_window *win) xdg_toplevel_destroy(win->xdg_toplevel); if (win->xdg_surface != NULL) xdg_surface_destroy(win->xdg_surface); - if (win->surface != NULL) - wl_surface_destroy(win->surface); + if (win->surface.surf != NULL) + wl_surface_destroy(win->surface.surf); wayl_roundtrip(win->term->wl); @@ -1880,7 +1884,7 @@ wayl_win_scale(struct wl_window *win) const struct wayland *wayl = term->wl; const float scale = term->scale; - wayl_surface_scale(wayl, win->surface, scale); + wayl_surface_scale(wayl, win->surface.surf, scale); } void @@ -1894,11 +1898,11 @@ wayl_win_alpha_changed(struct wl_window *win) if (region != NULL) { wl_region_add(region, 0, 0, INT32_MAX, INT32_MAX); - wl_surface_set_opaque_region(win->surface, region); + wl_surface_set_opaque_region(win->surface.surf, region); wl_region_destroy(region); } } else - wl_surface_set_opaque_region(win->surface, NULL); + wl_surface_set_opaque_region(win->surface.surf, NULL); } #if defined(HAVE_XDG_ACTIVATION) @@ -1909,7 +1913,7 @@ activation_token_for_urgency_done(const char *token, void *data) struct wayland *wayl = win->term->wl; win->urgency_token_is_pending = false; - xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface); + xdg_activation_v1_activate(wayl->xdg_activation, token, win->surface.surf); } #endif /* HAVE_XDG_ACTIVATION */ @@ -1954,11 +1958,11 @@ wayl_win_csd_borders_visible(const struct wl_window *win) bool wayl_win_subsurface_new_with_custom_parent( struct wl_window *win, struct wl_surface *parent, - struct wl_surf_subsurf *surf, bool allow_pointer_input) + struct wayl_sub_surface *surf, bool allow_pointer_input) { struct wayland *wayl = win->term->wl; - surf->surf = NULL; + surf->surface.surf = NULL; surf->sub = NULL; struct wl_surface *main_surface @@ -2002,39 +2006,42 @@ wayl_win_subsurface_new_with_custom_parent( wl_region_destroy(empty); } - surf->surf = main_surface; + surf->surface.surf = main_surface; surf->sub = sub; #if defined(HAVE_FRACTIONAL_SCALE) - surf->viewport = viewport; + surf->surface.viewport = viewport; #endif return true; } bool -wayl_win_subsurface_new(struct wl_window *win, struct wl_surf_subsurf *surf, +wayl_win_subsurface_new(struct wl_window *win, struct wayl_sub_surface *surf, bool allow_pointer_input) { return wayl_win_subsurface_new_with_custom_parent( - win, win->surface, surf, allow_pointer_input); + win, win->surface.surf, surf, allow_pointer_input); } void -wayl_win_subsurface_destroy(struct wl_surf_subsurf *surf) +wayl_win_subsurface_destroy(struct wayl_sub_surface *surf) { if (surf == NULL) return; #if defined(HAVE_FRACTIONAL_SCALE) - if (surf->viewport != NULL) - wp_viewport_destroy(surf->viewport); + if (surf->surface.viewport != NULL) { + wp_viewport_destroy(surf->surface.viewport); + surf->surface.viewport = NULL; + } #endif - if (surf->sub != NULL) + if (surf->sub != NULL) { wl_subsurface_destroy(surf->sub); - if (surf->surf != NULL) - wl_surface_destroy(surf->surf); - - surf->surf = NULL; - surf->sub = NULL; + surf->sub = NULL; + } + if (surf->surface.surf != NULL) { + wl_surface_destroy(surf->surface.surf); + surf->surface.surf = NULL; + } } #if defined(HAVE_XDG_ACTIVATION) @@ -2099,7 +2106,7 @@ wayl_get_activation_token( if (seat != NULL && serial != 0) xdg_activation_token_v1_set_serial(token, serial, seat->wl_seat); - xdg_activation_token_v1_set_surface(token, win->surface); + xdg_activation_token_v1_set_surface(token, win->surface.surf); xdg_activation_token_v1_add_listener(token, &activation_token_listener, ctx); xdg_activation_token_v1_commit(token); return true; diff --git a/wayland.h b/wayland.h index bb9bf77f..3ad05d33 100644 --- a/wayland.h +++ b/wayland.h @@ -45,6 +45,18 @@ enum data_offer_mime_type { DATA_OFFER_MIME_TEXT_UTF8_STRING, }; +struct wayl_surface { + struct wl_surface *surf; +#if defined(HAVE_FRACTIONAL_SCALE) + struct wp_viewport *viewport; +#endif +}; + +struct wayl_sub_surface { + struct wayl_surface surface; + struct wl_subsurface *sub; +}; + struct wl_window; struct wl_clipboard { struct wl_window *window; /* For DnD */ @@ -132,7 +144,7 @@ struct seat { struct { uint32_t serial; - struct wl_surface *surface; + struct wayl_surface surface; struct wl_cursor_theme *theme; struct wl_cursor *cursor; float scale; @@ -294,17 +306,9 @@ struct monitor { bool use_output_release; }; -struct wl_surf_subsurf { - struct wl_surface *surf; - struct wl_subsurface *sub; -#if defined(HAVE_FRACTIONAL_SCALE) - struct wp_viewport *viewport; -#endif -}; - struct wl_url { const struct url *url; - struct wl_surf_subsurf surf; + struct wayl_sub_surface surf; }; enum csd_mode {CSD_UNKNOWN, CSD_NO, CSD_YES}; @@ -328,7 +332,7 @@ struct xdg_activation_token_context { struct wayland; struct wl_window { struct terminal *term; - struct wl_surface *surface; + struct wayl_surface surface; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; #if defined(HAVE_XDG_ACTIVATION) @@ -336,7 +340,6 @@ struct wl_window { bool urgency_token_is_pending; #endif #if defined(HAVE_FRACTIONAL_SCALE) - struct wp_viewport *viewport; struct wp_fractional_scale_v1 *fractional_scale; #endif bool unmapped; @@ -348,7 +351,7 @@ struct wl_window { enum csd_mode csd_mode; struct { - struct wl_surf_subsurf surface[CSD_SURF_COUNT]; + struct wayl_sub_surface surface[CSD_SURF_COUNT]; struct fcft_font *font; int move_timeout_fd; uint32_t serial; @@ -359,10 +362,10 @@ struct wl_window { bool minimize:1; } wm_capabilities; - struct wl_surf_subsurf search; - struct wl_surf_subsurf scrollback_indicator; - struct wl_surf_subsurf render_timer; - struct wl_surf_subsurf overlay; + struct wayl_sub_surface search; + struct wayl_sub_surface scrollback_indicator; + struct wayl_sub_surface render_timer; + struct wayl_sub_surface overlay; struct wl_callback *frame_callback; @@ -465,12 +468,12 @@ bool wayl_win_csd_titlebar_visible(const struct wl_window *win); bool wayl_win_csd_borders_visible(const struct wl_window *win); bool wayl_win_subsurface_new( - struct wl_window *win, struct wl_surf_subsurf *surf, + struct wl_window *win, struct wayl_sub_surface *surf, bool allow_pointer_input); bool wayl_win_subsurface_new_with_custom_parent( struct wl_window *win, struct wl_surface *parent, - struct wl_surf_subsurf *surf, bool allow_pointer_input); -void wayl_win_subsurface_destroy(struct wl_surf_subsurf *surf); + struct wayl_sub_surface *surf, bool allow_pointer_input); +void wayl_win_subsurface_destroy(struct wayl_sub_surface *surf); #if defined(HAVE_XDG_ACTIVATION) bool wayl_get_activation_token( From 434fd6aa1f4a21ef6572a772ec891eeb2006a82c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 16:53:16 +0200 Subject: [PATCH 18/33] wayland: refactor: wayl_surface_scale(): pass wayl_surface pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of passing a raw wl_surface pointer, pass a wayl_surface pointer. This is needed later, when using fractional scaling to scale the surface (since then we need the surface’s viewport object). --- render.c | 61 +++++++++++++++++++++++++------------------------------ wayland.c | 6 +++--- wayland.h | 2 +- 3 files changed, 32 insertions(+), 37 deletions(-) diff --git a/render.c b/render.c index 5ebd69eb..e78f1eeb 100644 --- a/render.c +++ b/render.c @@ -1691,7 +1691,7 @@ render_overlay(struct terminal *term) &(pixman_rectangle16_t){0, 0, term->width, term->height}); quirk_weston_subsurface_desync_on(overlay->sub); - wayl_surface_scale(term->wl, overlay->surface.surf, term->scale); + wayl_surface_scale(term->wl, &overlay->surface, term->scale); wl_subsurface_set_position(overlay->sub, 0, 0); wl_surface_attach(overlay->surface.surf, buf->wl_buf, 0, 0); @@ -1828,12 +1828,12 @@ 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) +csd_commit(struct terminal *term, struct wayl_surface *surf, struct buffer *buf) { wayl_surface_scale(term->wl, surf, term->scale); - wl_surface_attach(surf, buf->wl_buf, 0, 0); - wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height); - wl_surface_commit(surf); + wl_surface_attach(surf->surf, buf->wl_buf, 0, 0); + wl_surface_damage_buffer(surf->surf, 0, 0, buf->width, buf->height); + wl_surface_commit(surf->surf); } static void @@ -1849,8 +1849,7 @@ render_csd_part(struct terminal *term, } static void -render_osd(struct terminal *term, - struct wl_surface *surf, struct wl_subsurface *sub_surf, +render_osd(struct terminal *term, const struct wayl_sub_surface *sub_surf, struct fcft_font *font, struct buffer *buf, const char32_t *text, uint32_t _fg, uint32_t _bg, unsigned x, unsigned y) @@ -1923,20 +1922,20 @@ render_osd(struct terminal *term, pixman_image_unref(src); pixman_image_set_clip_region32(buf->pix[0], NULL); - quirk_weston_subsurface_desync_on(sub_surf); - wayl_surface_scale(term->wl, surf, term->scale); - wl_surface_attach(surf, buf->wl_buf, 0, 0); - wl_surface_damage_buffer(surf, 0, 0, buf->width, buf->height); + quirk_weston_subsurface_desync_on(sub_surf->sub); + wayl_surface_scale(term->wl, &sub_surf->surface, term->scale); + wl_surface_attach(sub_surf->surface.surf, buf->wl_buf, 0, 0); + wl_surface_damage_buffer(sub_surf->surface.surf, 0, 0, buf->width, buf->height); struct wl_region *region = wl_compositor_create_region(term->wl->compositor); if (region != NULL) { wl_region_add(region, 0, 0, buf->width, buf->height); - wl_surface_set_opaque_region(surf, region); + wl_surface_set_opaque_region(sub_surf->surface.surf, region); wl_region_destroy(region); } - wl_surface_commit(surf); - quirk_weston_subsurface_desync_off(sub_surf); + wl_surface_commit(sub_surf->surface.surf); + quirk_weston_subsurface_desync_off(sub_surf->sub); } static void @@ -1971,11 +1970,10 @@ render_csd_title(struct terminal *term, const struct csd_data *info, const int margin = M != NULL ? M->advance.x : win->csd.font->max_advance.x; - render_osd(term, surf->surface.surf, surf->sub, win->csd.font, - buf, title_text, fg, bg, margin, + render_osd(term, surf, win->csd.font, buf, title_text, fg, bg, margin, (buf->height - win->csd.font->height) / 2); - csd_commit(term, surf->surface.surf, buf); + csd_commit(term, &surf->surface, buf); free(_title_text); } @@ -1986,14 +1984,14 @@ render_csd_border(struct terminal *term, enum csd_surface surf_idx, xassert(term->window->csd_mode == CSD_YES); xassert(surf_idx >= CSD_SURF_LEFT && surf_idx <= CSD_SURF_BOTTOM); - struct wl_surface *surf = term->window->csd.surface[surf_idx].surface.surf; + struct wayl_surface *surf = &term->window->csd.surface[surf_idx].surface; if (info->width == 0 || info->height == 0) return; { pixman_color_t color = color_hex_to_pixman_with_alpha(0, 0); - render_csd_part(term, surf, buf, info->width, info->height, &color); + render_csd_part(term, surf->surf, buf, info->width, info->height, &color); } /* @@ -2271,7 +2269,7 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx, xassert(term->window->csd_mode == CSD_YES); xassert(surf_idx >= CSD_SURF_MINIMIZE && surf_idx <= CSD_SURF_CLOSE); - struct wl_surface *surf = term->window->csd.surface[surf_idx].surface.surf; + struct wayl_surface *surf = &term->window->csd.surface[surf_idx].surface; if (info->width == 0 || info->height == 0) return; @@ -2323,7 +2321,7 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx, _color = color_dim(term, _color); pixman_color_t color = color_hex_to_pixman_with_alpha(_color, alpha); - render_csd_part(term, surf, buf, info->width, info->height, &color); + render_csd_part(term, surf->surf, buf, info->width, info->height, &color); switch (surf_idx) { case CSD_SURF_MINIMIZE: render_csd_button_minimize(term, buf); break; @@ -2534,8 +2532,7 @@ render_scrollback_position(struct terminal *term) render_osd( term, - win->scrollback_indicator.surface.surf, - win->scrollback_indicator.sub, + &win->scrollback_indicator, term->fonts[0], buf, text, fg, 0xffu << 24 | bg, width - margin - c32len(text) * term->cell_width, margin); @@ -2571,8 +2568,7 @@ render_render_timer(struct terminal *term, struct timespec render_time) render_osd( term, - win->render_timer.surface.surf, - win->render_timer.sub, + &win->render_timer, term->fonts[0], buf, text, term->colors.table[0], 0xffu << 24 | term->colors.table[8 + 1], margin, margin); @@ -3374,7 +3370,7 @@ render_search_box(struct terminal *term) margin / term->scale, max(0, (int32_t)term->height - height - margin) / term->scale); - wayl_surface_scale(term->wl, term->window->search.surface.surf, term->scale); + wayl_surface_scale(term->wl, &term->window->search.surface, term->scale); wl_surface_attach(term->window->search.surface.surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(term->window->search.surface.surf, 0, 0, width, height); @@ -3601,23 +3597,22 @@ render_urls(struct terminal *term) : term->colors.table[3]; for (size_t i = 0; i < render_count; i++) { - struct wl_surface *surf = info[i].url->surf.surface.surf; - struct wl_subsurface *sub_surf = info[i].url->surf.sub; + const struct wayl_sub_surface *sub_surf = &info[i].url->surf; const char32_t *label = info[i].text; const int x = info[i].x; const int y = info[i].y; - xassert(surf != NULL); - xassert(sub_surf != NULL); + xassert(sub_surf->surface.surf != NULL); + xassert(sub_surf->sub != NULL); wl_subsurface_set_position( - sub_surf, + sub_surf->sub, (term->margins.left + x) / term->scale, (term->margins.top + y) / term->scale); render_osd( - term, surf, sub_surf, term->fonts[0], bufs[i], label, + term, sub_surf, term->fonts[0], bufs[i], label, fg, 0xffu << 24 | bg, x_margin, y_margin); free(info[i].text); @@ -4263,7 +4258,7 @@ render_xcursor_update(struct seat *seat) const float scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; - wayl_surface_scale(seat->wayl, seat->pointer.surface.surf, scale); + wayl_surface_scale(seat->wayl, &seat->pointer.surface, scale); wl_surface_attach( seat->pointer.surface.surf, wl_cursor_image_get_buffer(image), 0, 0); diff --git a/wayland.c b/wayland.c index 3b6833c5..cd1a4c68 100644 --- a/wayland.c +++ b/wayland.c @@ -1865,7 +1865,7 @@ wayl_fractional_scaling(const struct wayland *wayl) } void -wayl_surface_scale(const struct wayland *wayl, struct wl_surface *surf, +wayl_surface_scale(const struct wayland *wayl, const struct wayl_surface *surf, float scale) { LOG_WARN("scaling by a factor of %.2f (legacy)", scale); @@ -1873,7 +1873,7 @@ wayl_surface_scale(const struct wayland *wayl, struct wl_surface *surf, if (wayl_fractional_scaling(wayl)) { BUG("not yet implemented"); } else { - wl_surface_set_buffer_scale(surf, (int)scale); + wl_surface_set_buffer_scale(surf->surf, (int)scale); } } @@ -1884,7 +1884,7 @@ wayl_win_scale(struct wl_window *win) const struct wayland *wayl = term->wl; const float scale = term->scale; - wayl_surface_scale(wayl, win->surface.surf, scale); + wayl_surface_scale(wayl, &win->surface, scale); } void diff --git a/wayland.h b/wayland.h index 3ad05d33..0506f82b 100644 --- a/wayland.h +++ b/wayland.h @@ -455,7 +455,7 @@ void wayl_roundtrip(struct wayland *wayl); bool wayl_fractional_scaling(const struct wayland *wayl); void wayl_surface_scale( - const struct wayland *wayl, struct wl_surface *surf, float scale); + const struct wayland *wayl, const struct wayl_surface *surf, float scale); struct wl_window *wayl_win_init(struct terminal *term, const char *token); void wayl_win_destroy(struct wl_window *win); From 5a60bbc119397c2993fc1895bae75c2c1e69fe1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 17:05:16 +0200 Subject: [PATCH 19/33] wayland: refactor: add a buffer argument to wayl_*_scale() functions This will be needed later, when using fractional scaling + viewporter to scale. --- render.c | 28 +++++++++++++++++----------- wayland.c | 17 +++++++++++++---- wayland.h | 9 +++++++-- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/render.c b/render.c index e78f1eeb..72d87bff 100644 --- a/render.c +++ b/render.c @@ -1691,7 +1691,8 @@ render_overlay(struct terminal *term) &(pixman_rectangle16_t){0, 0, term->width, term->height}); quirk_weston_subsurface_desync_on(overlay->sub); - wayl_surface_scale(term->wl, &overlay->surface, term->scale); + wayl_surface_scale( + term->wl, &overlay->surface, buf, term->scale); wl_subsurface_set_position(overlay->sub, 0, 0); wl_surface_attach(overlay->surface.surf, buf->wl_buf, 0, 0); @@ -1830,7 +1831,7 @@ get_csd_data(const struct terminal *term, enum csd_surface surf_idx) static void csd_commit(struct terminal *term, struct wayl_surface *surf, struct buffer *buf) { - wayl_surface_scale(term->wl, surf, term->scale); + wayl_surface_scale(term->wl, surf, buf, term->scale); wl_surface_attach(surf->surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(surf->surf, 0, 0, buf->width, buf->height); wl_surface_commit(surf->surf); @@ -1923,7 +1924,7 @@ render_osd(struct terminal *term, const struct wayl_sub_surface *sub_surf, pixman_image_set_clip_region32(buf->pix[0], NULL); quirk_weston_subsurface_desync_on(sub_surf->sub); - wayl_surface_scale(term->wl, &sub_surf->surface, term->scale); + wayl_surface_scale(term->wl, &sub_surf->surface, buf, term->scale); wl_surface_attach(sub_surf->surface.surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(sub_surf->surface.surf, 0, 0, buf->width, buf->height); @@ -3013,7 +3014,7 @@ grid_render(struct terminal *term) term->window->frame_callback = wl_surface_frame(term->window->surface.surf); wl_callback_add_listener(term->window->frame_callback, &frame_listener, term); - wayl_win_scale(term->window); + wayl_win_scale(term->window, buf); if (term->wl->presentation != NULL && term->conf->presentation_timings) { struct timespec commit_time; @@ -3370,7 +3371,7 @@ render_search_box(struct terminal *term) margin / term->scale, max(0, (int32_t)term->height - height - margin) / term->scale); - wayl_surface_scale(term->wl, &term->window->search.surface, term->scale); + wayl_surface_scale(term->wl, &term->window->search.surface, buf, term->scale); wl_surface_attach(term->window->search.surface.surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(term->window->search.surface.surf, 0, 0, width, height); @@ -3843,9 +3844,13 @@ maybe_resize(struct terminal *term, int width, int height, bool force) return false; float scale = -1; - tll_foreach(term->window->on_outputs, it) { - if (it->item->scale > scale) - scale = it->item->scale; + if (wayl_fractional_scaling(term->wl)) { + scale = term->window->scale; + } else { + tll_foreach(term->window->on_outputs, it) { + if (it->item->scale > scale) + scale = it->item->scale; + } } if (scale < 0.) { @@ -4257,11 +4262,12 @@ render_xcursor_update(struct seat *seat) const float scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; + struct wl_buffer *buf = wl_cursor_image_get_buffer(image); - wayl_surface_scale(seat->wayl, &seat->pointer.surface, scale); + wayl_surface_scale_explicit_width_height( + seat->wayl, &seat->pointer.surface, image->width, image->height, scale); - wl_surface_attach( - seat->pointer.surface.surf, wl_cursor_image_get_buffer(image), 0, 0); + wl_surface_attach(seat->pointer.surface.surf, buf, 0, 0); wl_pointer_set_cursor( seat->wl_pointer, seat->pointer.serial, diff --git a/wayland.c b/wayland.c index cd1a4c68..43f85066 100644 --- a/wayland.c +++ b/wayland.c @@ -1865,8 +1865,9 @@ wayl_fractional_scaling(const struct wayland *wayl) } void -wayl_surface_scale(const struct wayland *wayl, const struct wayl_surface *surf, - float scale) +wayl_surface_scale_explicit_width_height( + const struct wayland *wayl, const struct wayl_surface *surf, + int width, int height, float scale) { LOG_WARN("scaling by a factor of %.2f (legacy)", scale); @@ -1878,13 +1879,21 @@ wayl_surface_scale(const struct wayland *wayl, const struct wayl_surface *surf, } void -wayl_win_scale(struct wl_window *win) +wayl_surface_scale(const struct wayland *wayl, const struct wayl_surface *surf, + const struct buffer *buf, float scale) +{ + wayl_surface_scale_explicit_width_height( + wayl, surf, buf->width, buf->height, scale); +} + +void +wayl_win_scale(struct wl_window *win, const struct buffer *buf) { const struct terminal *term = win->term; const struct wayland *wayl = term->wl; const float scale = term->scale; - wayl_surface_scale(wayl, &win->surface, scale); + wayl_surface_scale(wayl, &win->surface, buf, scale); } void diff --git a/wayland.h b/wayland.h index 0506f82b..9736ea4d 100644 --- a/wayland.h +++ b/wayland.h @@ -32,6 +32,7 @@ /* Forward declarations */ struct terminal; +struct buffer; /* Mime-types we support when dealing with data offers (e.g. copy-paste, or DnD) */ enum data_offer_mime_type { @@ -455,12 +456,16 @@ void wayl_roundtrip(struct wayland *wayl); bool wayl_fractional_scaling(const struct wayland *wayl); void wayl_surface_scale( - const struct wayland *wayl, const struct wayl_surface *surf, float scale); + const struct wayland *wayl, const struct wayl_surface *surf, + const struct buffer *buf, float scale); +void wayl_surface_scale_explicit_width_height( + const struct wayland *wayl, const struct wayl_surface *surf, + int width, int height, float scale); struct wl_window *wayl_win_init(struct terminal *term, const char *token); void wayl_win_destroy(struct wl_window *win); -void wayl_win_scale(struct wl_window *win); +void wayl_win_scale(struct wl_window *win, const struct buffer *buf); void wayl_win_alpha_changed(struct wl_window *win); bool wayl_win_set_urgent(struct wl_window *win); From e5989d81b931afb31ac0ac3df9269841adef2d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 17:31:14 +0200 Subject: [PATCH 20/33] wayland: instantiate+destroy viewport for pointer surface --- wayland.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/wayland.c b/wayland.c index 43f85066..6dea027d 100644 --- a/wayland.c +++ b/wayland.c @@ -293,13 +293,27 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, if (caps & WL_SEAT_CAPABILITY_POINTER) { if (seat->wl_pointer == NULL) { xassert(seat->pointer.surface.surf == NULL); - seat->pointer.surface.surf = wl_compositor_create_surface(seat->wayl->compositor); + seat->pointer.surface.surf = + wl_compositor_create_surface(seat->wayl->compositor); if (seat->pointer.surface.surf == NULL) { LOG_ERR("%s: failed to create pointer surface", seat->name); return; } +#if defined(HAVE_FRACTIONAL_SCALE) + xassert(seat->pointer.surface.viewport == NULL); + seat->pointer.surface.viewport = wp_viewporter_get_viewport( + seat->wayl->viewporter, seat->pointer.surface.surf); + + if (seat->pointer.surface.viewport == NULL) { + LOG_ERR("%s: failed to create pointer viewport", seat->name); + wl_surface_destroy(seat->pointer.surface.surf); + seat->pointer.surface.surf = NULL; + return; + } +#endif + seat->wl_pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat); } @@ -308,6 +322,11 @@ seat_handle_capabilities(void *data, struct wl_seat *wl_seat, wl_pointer_release(seat->wl_pointer); wl_surface_destroy(seat->pointer.surface.surf); +#if defined(HAVE_FRACTIONAL_SCALE) + wp_viewport_destroy(seat->pointer.surface.viewport); + seat->pointer.surface.viewport = NULL; +#endif + if (seat->pointer.theme != NULL) wl_cursor_theme_destroy(seat->pointer.theme); From 36818459e51d99bdb9f48bf0b7a9471c4b8fe67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 17:31:39 +0200 Subject: [PATCH 21/33] wayland: initialize window scale to -1 --- wayland.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wayland.c b/wayland.c index 6dea027d..a45171ff 100644 --- a/wayland.c +++ b/wayland.c @@ -1550,6 +1550,7 @@ wayl_win_init(struct terminal *term, const char *token) win->csd_mode = CSD_UNKNOWN; win->csd.move_timeout_fd = -1; win->resize_timeout_fd = -1; + win->scale = -1.; win->wm_capabilities.maximize = true; win->wm_capabilities.minimize = true; From 8ccabb79745f079417b3a049f52c4779d6efdf07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 17:32:01 +0200 Subject: [PATCH 22/33] wayland: surface_scale(): implement fractional scaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is done by setting the surface’s viewport destination --- wayland.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/wayland.c b/wayland.c index a45171ff..fce6a67f 100644 --- a/wayland.c +++ b/wayland.c @@ -1889,11 +1889,20 @@ wayl_surface_scale_explicit_width_height( const struct wayland *wayl, const struct wayl_surface *surf, int width, int height, float scale) { - LOG_WARN("scaling by a factor of %.2f (legacy)", scale); if (wayl_fractional_scaling(wayl)) { - BUG("not yet implemented"); +#if defined(HAVE_FRACTIONAL_SCALE) + LOG_DBG("scaling by a factor of %.2f (fractional scaling)", scale); + wp_viewport_set_destination( + surf->viewport, + round((float)width / scale), + round((float)height / scale)); +#else + BUG("wayl_fraction_scaling() returned true, " + "but fractional scaling was not available at compile time"). +#endif } else { + LOG_DBG("scaling by a factor of %.2f (legacy)", scale); wl_surface_set_buffer_scale(surf->surf, (int)scale); } } From 0bdb6580bd5f470ca82e771c70a8f7cd4f5a0240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 17:32:33 +0200 Subject: [PATCH 23/33] wayland: update terminal when preferred scaling factor changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the window’s preferred scaling factor is changed (through the fractional-scaling protocol), update the terminal; resize font, resize sub-surfaces etc. --- wayland.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/wayland.c b/wayland.c index fce6a67f..683338c0 100644 --- a/wayland.c +++ b/wayland.c @@ -1526,7 +1526,9 @@ static void fractional_scale_preferred_scale( { struct wl_window *win = data; win->scale = (float)scale / 120.; + LOG_DBG("fractional scale: %.3f", win->scale); + update_term_for_output_change(win->term); } static const struct wp_fractional_scale_v1_listener fractional_scale_listener = { From 32b8c5c9b6628f3dd1b9f25f9b13a6d016de86cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 17:34:20 +0200 Subject: [PATCH 24/33] changelog: mention the newly added support for fractional-scaling-v1 --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 943dd411..c3e66216 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,9 @@ is `auto`, which will select `libutempter` on Linux, `ulog` on FreeBSD, and `none` for all others. * Sixel aspect ratio. +* Support for the new fractional-scaling-v1 Wayland protocol. This + brings true fractional scaling to Wayland in general, and with this + release, foot. ### Changed From 64b6b5d2a7b81bcad3f0a50a6c1556fd7300c171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 17:55:04 +0200 Subject: [PATCH 25/33] =?UTF-8?q?config:=20dpi-aware:=20remove=20=E2=80=98?= =?UTF-8?q?auto=E2=80=99=20value,=20and=20default=20to=20=E2=80=98no?= =?UTF-8?q?=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now default to scaling fonts using the scaling factor, not monitor DPI. The ‘auto’ value for dpi-aware has been removed. Documentation (man pages and README) have been updated to reflect the new default. --- README.md | 52 +++++++++++++++++++++++++++++++++------------ config.c | 15 +++---------- config.h | 2 +- doc/foot.ini.5.scd | 10 ++------- foot.ini | 2 +- terminal.c | 38 +-------------------------------- tests/test-config.c | 12 +---------- wayland.c | 5 ----- 8 files changed, 48 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index 8d037af3..0d6262dc 100644 --- a/README.md +++ b/README.md @@ -411,27 +411,53 @@ This is not how it is meant to be. Fonts are measured in _point sizes_ **for a reason**; a given point size should have the same height on all mediums, be it printers or monitors, regardless of their DPI. -Foot’s default behavior is to use the monitor’s DPI to size fonts when -output scaling has been disabled on **all** monitors. If at least one -monitor has output scaling enabled, fonts will instead by sized using -the scaling factor. +That said, on Wayland, Hi-DPI monitors are typically handled by +configuring a _"scaling factor"_ in the compositor. This is usually +expressed as either a rational value (e.g. _1.5_), or as a percentage +(e.g. _150%_), by which all fonts and window sizes are supposed to be +multiplied. -This can be changed to either **always** use the monitor’s DPI -(regardless of scaling factor), or to **never** use it, with the -`dpi-aware` option in `foot.ini`. See the man page, **foot.ini**(5) -for more information. +For this reason, and because of the new _fractional scaling_ protocol +(see below for details), and because this is how Wayland applications +are expected to behave, foot >= 1.15 will default to scaling fonts +using the compositor’s scaling factor, and **not** the monitor +DPI. -When fonts are sized using the monitor’s DPI, glyphs should always -have the same physical height, regardless of monitor. +This means the (assuming the monitors are at the same viewing +distance) the font size will appear to change when you move the foot +window across different monitors, **unless** you have configured the +monitors’ scaling factors correctly in the compositor. -Furthermore, foot will re-size the fonts on-the-fly when the window is -moved between screens with different DPIs values. If the window covers -multiple screens, with different DPIs, the highest DPI will be used. +This can be changed by setting the `dpi-aware` option to `yes` in +`foot.ini`. When enabled, fonts will **not** be sized using the +scaling factor, but will instead be sized using the monitor’s +DPI. When the foot window is moved across monitors, the font size is +updated for the current monitor’s DPI. + +This means that, assuming the monitors are **at the same viewing +distance**, the font size will appear to be the same, at all times. _Note_: if you configure **pixelsize**, rather than **size**, then DPI changes will **not** change the font size. Pixels are always pixels. +### Fractional scaling on Wayland + +For a long time, there was no **true** support for _fractional +scaling_. That is, values like 1.5 (150%), 1.8 (180%) etc, only +integer values, like 2 (200%). + +Compositors that _did_ support fractional scaling did so using a hack; +all applications were told to scale to 200%, and then the compositor +would down-scale the rendered image to e.g. 150%. This works OK for +everything **except fonts**, which ended up blurry. + +With _wayland-protocols 1.32_, a new protocol was introduced, that +allows compositors to tell applications the _actual_ scaling +factor. Applications can then scale the image using a _viewport_ +object, instead of setting a scale factor on the raw pixel buffer. + + ## Supported OSCs OSC, _Operating System Command_, are escape sequences that interacts diff --git a/config.c b/config.c index aba85db3..3d02355f 100644 --- a/config.c +++ b/config.c @@ -972,17 +972,8 @@ parse_section_main(struct context *ctx) else if (strcmp(key, "underline-thickness") == 0) return value_to_pt_or_px(ctx, &conf->underline_thickness); - else if (strcmp(key, "dpi-aware") == 0) { - if (strcmp(value, "auto") == 0) - conf->dpi_aware = DPI_AWARE_AUTO; - else { - bool value; - if (!value_to_bool(ctx, &value)) - return false; - conf->dpi_aware = value ? DPI_AWARE_YES : DPI_AWARE_NO; - } - return true; - } + else if (strcmp(key, "dpi-aware") == 0) + return value_to_bool(ctx, &conf->dpi_aware); else if (strcmp(key, "workers") == 0) return value_to_uint16(ctx, 10, &conf->render_worker_count); @@ -2939,7 +2930,7 @@ config_load(struct config *conf, const char *conf_path, .use_custom_underline_offset = false, .box_drawings_uses_font_glyphs = false, .underline_thickness = {.pt = 0., .px = -1}, - .dpi_aware = DPI_AWARE_AUTO, /* DPI-aware when scaling-factor == 1 */ + .dpi_aware = false, .bell = { .urgent = false, .notify = false, diff --git a/config.h b/config.h index ce1ee536..2034752f 100644 --- a/config.h +++ b/config.h @@ -137,7 +137,7 @@ struct config { enum { STARTUP_WINDOWED, STARTUP_MAXIMIZED, STARTUP_FULLSCREEN } startup_mode; - enum {DPI_AWARE_AUTO, DPI_AWARE_YES, DPI_AWARE_NO} dpi_aware; + bool dpi_aware; struct config_font_list fonts[4]; struct font_size_adjustment font_size_adjustment; diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index f9174fc6..e28cf416 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -185,7 +185,7 @@ empty string to be set, but it must be quoted: *KEY=""*) Default: _no_. *dpi-aware* - *auto*, *yes*, or *no*. + Boolean. When set to *yes*, fonts are sized using the monitor's DPI, making a font of a given size have the same physical size, regardless of @@ -199,12 +199,6 @@ empty string to be set, but it must be quoted: *KEY=""*) instead sized using the monitor's scaling factor; doubling the scaling factor *does* double the font size. - Finally, if set to *auto*, fonts will be sized using the monitor's - DPI if _all_ monitors have a scaling factor of 1. If at least one - monitor as a scaling factor larger than 1 (regardless of whether - the foot window is mapped on that monitor or not), fonts will be - scaled using the scaling factor. - Note that this option typically does not work with bitmap fonts, which only contains a pre-defined set of sizes, and cannot be dynamically scaled. Whichever size (of the available ones) that @@ -217,7 +211,7 @@ empty string to be set, but it must be quoted: *KEY=""*) to size the font (*dpi-aware=no*), the font's pixel size will be multiplied with the scaling factor. - Default: _auto_ + Default: _no_ *pad* Padding between border and glyphs, in pixels (subject to output diff --git a/foot.ini b/foot.ini index a4b91ef7..61e88aec 100644 --- a/foot.ini +++ b/foot.ini @@ -20,7 +20,7 @@ # underline-offset= # underline-thickness= # box-drawings-uses-font-glyphs=no -# dpi-aware=auto +# dpi-aware=no # initial-window-size-pixels=700x500 # Or, # initial-window-size-chars= diff --git a/terminal.c b/terminal.c index 825e1550..090cbb20 100644 --- a/terminal.c +++ b/terminal.c @@ -912,42 +912,6 @@ get_font_subpixel(const struct terminal *term) return FCFT_SUBPIXEL_DEFAULT; } -static bool -term_font_size_by_dpi(const struct terminal *term) -{ - switch (term->conf->dpi_aware) { - case DPI_AWARE_YES: return true; - case DPI_AWARE_NO: return false; - - case DPI_AWARE_AUTO: - /* - * Scale using DPI if all monitors have a scaling factor or 1. - * - * The idea is this: if a user, with multiple monitors, have - * enabled scaling on at least one monitor, then he/she has - * most likely done so to match the size of his/hers other - * monitors. - * - * I.e. if the user has one monitor with a scaling factor of - * one, and another with a scaling factor of two, he/she - * expects things to be twice as large on the second - * monitor. - * - * If we (foot) scale using DPI on the first monitor, and - * using the scaling factor on the second monitor, foot will - * *not* look twice as big on the second monitor. - */ - tll_foreach(term->wl->monitors, it) { - const struct monitor *mon = &it->item; - if (mon->scale > 1) - return false; - } - return true; - } - - BUG("unhandled DPI awareness value"); -} - int term_pt_or_px_as_pixels(const struct terminal *term, const struct pt_or_px *pt_or_px) @@ -2158,7 +2122,7 @@ term_font_dpi_changed(struct terminal *term, int old_scale) xassert(term->scale > 0); bool was_scaled_using_dpi = term->font_is_sized_by_dpi; - bool will_scale_using_dpi = term_font_size_by_dpi(term); + bool will_scale_using_dpi = term->conf->dpi_aware; bool need_font_reload = was_scaled_using_dpi != will_scale_using_dpi || diff --git a/tests/test-config.c b/tests/test-config.c index b14f28b1..c70f7a43 100644 --- a/tests/test-config.c +++ b/tests/test-config.c @@ -511,6 +511,7 @@ test_section_main(void) test_boolean(&ctx, &parse_section_main, "box-drawings-uses-font-glyphs", &conf.box_drawings_uses_font_glyphs); test_boolean(&ctx, &parse_section_main, "locked-title", &conf.locked_title); test_boolean(&ctx, &parse_section_main, "notify-focus-inhibit", &conf.notify_focus_inhibit); + test_boolean(&ctx, &parse_section_main, "dpi-aware", &conf.dpi_aware); test_pt_or_px(&ctx, &parse_section_main, "font-size-adjustment", &conf.font_size_adjustment.pt_or_px); /* TODO: test ‘N%’ values too */ test_pt_or_px(&ctx, &parse_section_main, "line-height", &conf.line_height); @@ -524,17 +525,6 @@ test_section_main(void) test_spawn_template(&ctx, &parse_section_main, "notify", &conf.notify); - test_enum( - &ctx, &parse_section_main, "dpi-aware", - 9, - (const char *[]){"on", "true", "yes", "1", - "off", "false", "no", "0", - "auto"}, - (int []){DPI_AWARE_YES, DPI_AWARE_YES, DPI_AWARE_YES, DPI_AWARE_YES, - DPI_AWARE_NO, DPI_AWARE_NO, DPI_AWARE_NO, DPI_AWARE_NO, - DPI_AWARE_AUTO}, - (int *)&conf.dpi_aware); - test_enum(&ctx, &parse_section_main, "selection-target", 4, (const char *[]){"none", "primary", "clipboard", "both"}, diff --git a/wayland.c b/wayland.c index 683338c0..0f5cad2b 100644 --- a/wayland.c +++ b/wayland.c @@ -373,11 +373,6 @@ update_terms_on_monitor(struct monitor *mon) tll_foreach(wayl->terms, it) { struct terminal *term = it->item; - if (term->conf->dpi_aware == DPI_AWARE_AUTO) { - update_term_for_output_change(term); - continue; - } - tll_foreach(term->window->on_outputs, it2) { if (it2->item == mon) { update_term_for_output_change(term); From 27a92b11588203c90c0ec4c61a1a6c7a741b2935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 17:55:59 +0200 Subject: [PATCH 26/33] =?UTF-8?q?changelog:=20dpi-aware=E2=80=99s=20defaul?= =?UTF-8?q?t=20value=20is=20now=20=E2=80=98no=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3e66216..ff63610e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,8 @@ is explicitly added. * Default sixel aspect ratio is now 2:1 instead of 1:1. * Sixel images are no longer cropped to the last non-transparent row. +* `dpi-aware` now defaults to `no`, and the `auto` value has been + removed. [1371]: https://codeberg.org/dnkl/foot/pulls/1371 @@ -92,6 +94,10 @@ ### Removed + +* `auto` value for the `dpi-aware` option. + + ### Fixed * Incorrect icon in dock and window switcher on Gnome ([#1317][1317]) From 9db92bd942706d6d0ca0250d6011c49ec88f4051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 18:00:01 +0200 Subject: [PATCH 27/33] feature: add a feature flag (for --version) for fractional scaling --- client.c | 4 +++- foot-features.h | 9 +++++++++ main.c | 4 +++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/client.c b/client.c index 6954d17e..84bfb2c3 100644 --- a/client.c +++ b/client.c @@ -66,11 +66,13 @@ static const char * version_and_features(void) { static char buf[256]; - snprintf(buf, sizeof(buf), "version: %s %cpgo %cime %cgraphemes %cassertions", + snprintf(buf, sizeof(buf), + "version: %s %cpgo %cime %cgraphemes %cfractional-scaling %cassertions", FOOT_VERSION, feature_pgo() ? '+' : '-', feature_ime() ? '+' : '-', feature_graphemes() ? '+' : '-', + feature_fractional_scaling() ? '+' : ':', feature_assertions() ? '+' : '-'); return buf; } diff --git a/foot-features.h b/foot-features.h index ad447767..77923aaf 100644 --- a/foot-features.h +++ b/foot-features.h @@ -37,3 +37,12 @@ static inline bool feature_graphemes(void) return false; #endif } + +static inline bool feature_fractional_scaling(void) +{ +#if defined(HAVE_FRACTIONAL_SCALE) + return true; +#else + return false; +#endif +} diff --git a/main.c b/main.c index f58e170f..6dd9e468 100644 --- a/main.c +++ b/main.c @@ -52,11 +52,13 @@ static const char * version_and_features(void) { static char buf[256]; - snprintf(buf, sizeof(buf), "version: %s %cpgo %cime %cgraphemes %cassertions", + snprintf(buf, sizeof(buf), + "version: %s %cpgo %cime %cgraphemes %cfractional-scaling %cassertions", FOOT_VERSION, feature_pgo() ? '+' : '-', feature_ime() ? '+' : '-', feature_graphemes() ? '+' : '-', + feature_fractional_scaling() ? '+' : '-', feature_assertions() ? '+' : '-'); return buf; } From 8a4efb34276e9f15a65304477c40e71aa281f7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 18:37:49 +0200 Subject: [PATCH 28/33] =?UTF-8?q?wayland:=20warn=20when=20fractional=20sca?= =?UTF-8?q?ling=20isn=E2=80=99t=20available?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- wayland.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/wayland.c b/wayland.c index 0f5cad2b..28bb2b6f 100644 --- a/wayland.c +++ b/wayland.c @@ -1386,6 +1386,14 @@ wayl_init(struct fdm *fdm, struct key_binding_manager *key_binding_manager, "bell.urgent will fall back to coloring the window margins red"); } +#if defined(HAVE_FRACTIONAL_SCALE) + if (wayl->fractional_scale_manager == NULL || wayl->viewporter == NULL) { +#else + if (true) { +#endif + LOG_WARN("fractional scaling not available"); + } + if (presentation_timings && wayl->presentation == NULL) { LOG_ERR("presentation time interface not implemented by compositor"); goto out; From c309c9f572a331881c515d7715d474ef854ea958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 20:25:16 +0200 Subject: [PATCH 29/33] wayland: surface_scale(): assert surface width/height is a multiple of scale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When doing legacy scaling (non-fractional scaling), assert the surface’s width and height are multiples of the (integer) scale. --- wayland.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wayland.c b/wayland.c index 28bb2b6f..ce0e879f 100644 --- a/wayland.c +++ b/wayland.c @@ -1908,6 +1908,13 @@ wayl_surface_scale_explicit_width_height( #endif } else { LOG_DBG("scaling by a factor of %.2f (legacy)", scale); + + xassert(scale == floor(scale)); + + const int iscale = (int)scale; + xassert(width % iscale == 0); + xassert(height % iscale == 0); + wl_surface_set_buffer_scale(surf->surf, (int)scale); } } From d71e588800fea0f7b7815cc5ce51ded752070b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 21:06:47 +0200 Subject: [PATCH 30/33] wayland: refactor: surface_scale(): pass wl_window pointer, instead of wayland global --- render.c | 11 ++++++----- wayland.c | 11 +++++------ wayland.h | 4 ++-- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/render.c b/render.c index 72d87bff..11b5223a 100644 --- a/render.c +++ b/render.c @@ -1692,7 +1692,7 @@ render_overlay(struct terminal *term) quirk_weston_subsurface_desync_on(overlay->sub); wayl_surface_scale( - term->wl, &overlay->surface, buf, term->scale); + term->window, &overlay->surface, buf, term->scale); wl_subsurface_set_position(overlay->sub, 0, 0); wl_surface_attach(overlay->surface.surf, buf->wl_buf, 0, 0); @@ -1831,7 +1831,7 @@ get_csd_data(const struct terminal *term, enum csd_surface surf_idx) static void csd_commit(struct terminal *term, struct wayl_surface *surf, struct buffer *buf) { - wayl_surface_scale(term->wl, surf, buf, term->scale); + wayl_surface_scale(term->window, surf, buf, term->scale); wl_surface_attach(surf->surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(surf->surf, 0, 0, buf->width, buf->height); wl_surface_commit(surf->surf); @@ -1924,7 +1924,7 @@ render_osd(struct terminal *term, const struct wayl_sub_surface *sub_surf, pixman_image_set_clip_region32(buf->pix[0], NULL); quirk_weston_subsurface_desync_on(sub_surf->sub); - wayl_surface_scale(term->wl, &sub_surf->surface, buf, term->scale); + wayl_surface_scale(term->window, &sub_surf->surface, buf, term->scale); wl_surface_attach(sub_surf->surface.surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(sub_surf->surface.surf, 0, 0, buf->width, buf->height); @@ -3371,7 +3371,7 @@ render_search_box(struct terminal *term) margin / term->scale, max(0, (int32_t)term->height - height - margin) / term->scale); - wayl_surface_scale(term->wl, &term->window->search.surface, buf, term->scale); + wayl_surface_scale(term->window, &term->window->search.surface, buf, term->scale); wl_surface_attach(term->window->search.surface.surf, buf->wl_buf, 0, 0); wl_surface_damage_buffer(term->window->search.surface.surf, 0, 0, width, height); @@ -4265,7 +4265,8 @@ render_xcursor_update(struct seat *seat) struct wl_buffer *buf = wl_cursor_image_get_buffer(image); wayl_surface_scale_explicit_width_height( - seat->wayl, &seat->pointer.surface, image->width, image->height, scale); + seat->mouse_focus->window, + &seat->pointer.surface, image->width, image->height, scale); wl_surface_attach(seat->pointer.surface.surf, buf, 0, 0); diff --git a/wayland.c b/wayland.c index ce0e879f..aa1b298c 100644 --- a/wayland.c +++ b/wayland.c @@ -1891,7 +1891,7 @@ wayl_fractional_scaling(const struct wayland *wayl) void wayl_surface_scale_explicit_width_height( - const struct wayland *wayl, const struct wayl_surface *surf, + const struct wl_window *win, const struct wayl_surface *surf, int width, int height, float scale) { @@ -1915,26 +1915,25 @@ wayl_surface_scale_explicit_width_height( xassert(width % iscale == 0); xassert(height % iscale == 0); - wl_surface_set_buffer_scale(surf->surf, (int)scale); + wl_surface_set_buffer_scale(surf->surf, iscale); } } void -wayl_surface_scale(const struct wayland *wayl, const struct wayl_surface *surf, +wayl_surface_scale(const struct wl_window *win, const struct wayl_surface *surf, const struct buffer *buf, float scale) { wayl_surface_scale_explicit_width_height( - wayl, surf, buf->width, buf->height, scale); + win, surf, buf->width, buf->height, scale); } void wayl_win_scale(struct wl_window *win, const struct buffer *buf) { const struct terminal *term = win->term; - const struct wayland *wayl = term->wl; const float scale = term->scale; - wayl_surface_scale(wayl, &win->surface, buf, scale); + wayl_surface_scale(win, &win->surface, buf, scale); } void diff --git a/wayland.h b/wayland.h index 9736ea4d..7305ade7 100644 --- a/wayland.h +++ b/wayland.h @@ -456,10 +456,10 @@ void wayl_roundtrip(struct wayland *wayl); bool wayl_fractional_scaling(const struct wayland *wayl); void wayl_surface_scale( - const struct wayland *wayl, const struct wayl_surface *surf, + const struct wl_window *win, const struct wayl_surface *surf, const struct buffer *buf, float scale); void wayl_surface_scale_explicit_width_height( - const struct wayland *wayl, const struct wayl_surface *surf, + const struct wl_window *win, const struct wayl_surface *surf, int width, int height, float scale); struct wl_window *wayl_win_init(struct terminal *term, const char *token); From 8f74b1090a6a5297ac7b6710420528ff56ed03d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 21:07:24 +0200 Subject: [PATCH 31/33] wayland: use legacy scaling until fractional_scale::preferred_scale() has been called This way, the initial frame is more likely to get scaled correctly; foot will guess the initial (integer) scale from the available monitors, and use that. By using legacy scaling, we force the compositor to down-scale the image to the correct scale factor. If we use the new fraction scaling method with an integer scaling factor, the initial frame gets rendered way too big. --- wayland.c | 3 ++- wayland.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/wayland.c b/wayland.c index aa1b298c..bf8f2682 100644 --- a/wayland.c +++ b/wayland.c @@ -1529,6 +1529,7 @@ static void fractional_scale_preferred_scale( { struct wl_window *win = data; win->scale = (float)scale / 120.; + win->have_preferred_scale = true; LOG_DBG("fractional scale: %.3f", win->scale); update_term_for_output_change(win->term); @@ -1895,7 +1896,7 @@ wayl_surface_scale_explicit_width_height( int width, int height, float scale) { - if (wayl_fractional_scaling(wayl)) { + if (wayl_fractional_scaling(win->term->wl) && win->have_preferred_scale) { #if defined(HAVE_FRACTIONAL_SCALE) LOG_DBG("scaling by a factor of %.2f (fractional scaling)", scale); wp_viewport_set_destination( diff --git a/wayland.h b/wayland.h index 7305ade7..e2d22031 100644 --- a/wayland.h +++ b/wayland.h @@ -346,6 +346,7 @@ struct wl_window { bool unmapped; float scale; + bool have_preferred_scale; struct zxdg_toplevel_decoration_v1 *xdg_toplevel_decoration; From c61247f317b8b0559feeda551e8e7e33b54d3b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 21:09:18 +0200 Subject: [PATCH 32/33] wayland: surface_scale(): improve debug logging --- wayland.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/wayland.c b/wayland.c index bf8f2682..cff432bb 100644 --- a/wayland.c +++ b/wayland.c @@ -1898,7 +1898,9 @@ wayl_surface_scale_explicit_width_height( if (wayl_fractional_scaling(win->term->wl) && win->have_preferred_scale) { #if defined(HAVE_FRACTIONAL_SCALE) - LOG_DBG("scaling by a factor of %.2f (fractional scaling)", scale); + LOG_DBG("scaling by a factor of %.2f using fractional scaling " + "(width=%d, height=%d) ", scale, width, height); + wp_viewport_set_destination( surf->viewport, round((float)width / scale), @@ -1908,7 +1910,8 @@ wayl_surface_scale_explicit_width_height( "but fractional scaling was not available at compile time"). #endif } else { - LOG_DBG("scaling by a factor of %.2f (legacy)", scale); + LOG_DBG("scaling by a factor of %.2f using legacy mode " + "(width=%d, height=%d)", scale, width, height); xassert(scale == floor(scale)); From ce31cc518a48d978c84448424d0d2a6bba4a5a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 26 Jun 2023 21:09:30 +0200 Subject: [PATCH 33/33] wayland: surface_scale(): reset buffer scale when using fractional scaling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the first frame uses legacy scaling, the surface may have a buffer scale > 1, which isn’t allowed. --- wayland.c | 1 + 1 file changed, 1 insertion(+) diff --git a/wayland.c b/wayland.c index cff432bb..c9693200 100644 --- a/wayland.c +++ b/wayland.c @@ -1901,6 +1901,7 @@ wayl_surface_scale_explicit_width_height( LOG_DBG("scaling by a factor of %.2f using fractional scaling " "(width=%d, height=%d) ", scale, width, height); + wl_surface_set_buffer_scale(surf->surf, 1); wp_viewport_set_destination( surf->viewport, round((float)width / scale),