From 21d99f8dced335826964ca96b8ba7ccac059e598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 17 Jul 2023 16:21:16 +0200 Subject: [PATCH] terminal: break out scaling factor updating, and reduce number of calls to render_resize() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Break out the logic that updates the terminal’s scaling factor value, from render_resize(), to a new function, term_update_scale(). This allows us to update the scaling factor without a full grid resize. We also change how we pick the scaling factor (when fractional scaling is not in use). Before, we’d use the highest scaling factor from all monitors we were mapped on. Now, we use the scaling factor from the monitor we were *last* mapped on. Then, add a boolean parameter to term_set_fonts(), and when false, *don’t* call render_resize_force(). Also change term_font_dpi_changed() to only return true if the font was changed in any way. Finally, rewrite update_term_for_output_change() to: * Call term_update_scale() before doing anything else * Call render_resize{,_force} *last*, and *only* if either the scale or the fonts were updated. This fixes several things: * A bug where we failed to update the fonts when fractional scaling was in use, and we guessed the initial scale/DPI wrong. The bug happened because updated the internal "preferred" scale value, and a later call to render_resize() updated the terminal’s scale value, but since that code path didn’t call term_font_dpi_changed() (and it shouldn’t), the fonts weren’t resized properly. * It ensures we only resize the grid *once* when the scaling factor, or DPI is changed. Before this, we’d resize it twice. And this happened when e.g. dragging the window between monitors. --- render.c | 29 ++++++------------------ terminal.c | 65 +++++++++++++++++++++++++++++++++++++++++------------- terminal.h | 1 + wayland.c | 34 +++++++++++++++++++++------- 4 files changed, 84 insertions(+), 45 deletions(-) diff --git a/render.c b/render.c index c40d07d0..11149b16 100644 --- a/render.c +++ b/render.c @@ -3841,21 +3841,7 @@ maybe_resize(struct terminal *term, int width, int height, bool force) if (term->cell_width == 0 && term->cell_height == 0) return false; - float scale = -1; - 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.) { - /* Haven't 'entered' an output yet? */ - scale = term->scale; - } - + const float scale = term->scale; width = round(width * scale); height = round(height * scale); @@ -3942,9 +3928,9 @@ maybe_resize(struct terminal *term, int width, int height, bool force) /* Drop out of URL mode */ urls_reset(term); + LOG_DBG("resized: size=%dx%d (scale=%.2f)", width, height, term->scale); term->width = width; term->height = height; - term->scale = scale; const uint32_t scrollback_lines = term->render.scrollback_lines; @@ -4148,12 +4134,11 @@ maybe_resize(struct terminal *term, int width, int height, bool force) sixel_reflow(term); -#if defined(_DEBUG) && LOG_ENABLE_DBG - LOG_DBG("resize: %dx%d, grid: cols=%d, rows=%d " + LOG_DBG("resized: grid: cols=%d, rows=%d " "(left-margin=%d, right-margin=%d, top-margin=%d, bottom-margin=%d)", - term->width, term->height, term->cols, term->rows, - term->margins.left, term->margins.right, term->margins.top, term->margins.bottom); -#endif + term->cols, term->rows, + term->margins.left, term->margins.right, + term->margins.top, term->margins.bottom); if (term->scroll_region.start >= term->rows) term->scroll_region.start = 0; @@ -4295,7 +4280,7 @@ render_xcursor_update(struct seat *seat) #endif LOG_DBG("setting %scursor shape using a client-side cursor surface", - shape == CURSOR_SHAPE_CUSTOM ? "custom " : ""); + seat->pointer.shape == CURSOR_SHAPE_CUSTOM ? "custom " : ""); const float scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; diff --git a/terminal.c b/terminal.c index a557d632..86cb365a 100644 --- a/terminal.c +++ b/terminal.c @@ -733,7 +733,8 @@ term_line_height_update(struct terminal *term) } static bool -term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) +term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4], + bool resize_grid) { for (size_t i = 0; i < 4; i++) { xassert(fonts[i] != NULL); @@ -777,11 +778,15 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) sixel_cell_size_changed(term); - /* Use force, since cell-width/height may have changed */ - render_resize_force( - term, - round(term->width / term->scale), - round(term->height / term->scale)); + /* Optimization - some code paths (are forced to) call + * render_resize() after this function */ + if (resize_grid) { + /* Use force, since cell-width/height may have changed */ + render_resize_force( + term, + round(term->width / term->scale), + round(term->height / term->scale)); + } return true; } @@ -899,7 +904,7 @@ font_loader_thread(void *_data) } static bool -reload_fonts(struct terminal *term) +reload_fonts(struct terminal *term, bool resize_grid) { const struct config *conf = term->conf; @@ -1026,7 +1031,7 @@ reload_fonts(struct terminal *term) } } - return success ? term_set_fonts(term, fonts) : success; + return success ? term_set_fonts(term, fonts, resize_grid) : success; } static bool @@ -1044,7 +1049,7 @@ load_fonts_from_conf(struct terminal *term) } } - return reload_fonts(term); + return reload_fonts(term, true); } static void fdm_client_terminated( @@ -1987,7 +1992,7 @@ term_font_size_adjust_by_points(struct terminal *term, float amount) } } - return reload_fonts(term); + return reload_fonts(term, true); } static bool @@ -2010,7 +2015,7 @@ term_font_size_adjust_by_pixels(struct terminal *term, int amount) } } - return reload_fonts(term); + return reload_fonts(term, true); } static bool @@ -2034,7 +2039,7 @@ term_font_size_adjust_by_percent(struct terminal *term, bool increment, float pe } } - return reload_fonts(term); + return reload_fonts(term, true); } bool @@ -2071,6 +2076,36 @@ term_font_size_reset(struct terminal *term) return load_fonts_from_conf(term); } +bool +term_update_scale(struct terminal *term) +{ + const struct wl_window *win = term->window; + + /* + * We have a number of “sources” we can use as scale. We choose + * the scale in the following order: + * + * - “preferred” scale, from the fractional-scale-v1 protocol + * - scaling factor of output we most recently were mapped on + * - if we’re not mapped, use the scaling factor from the first + * available output. + * - if there aren’t any outputs available, use 1.0 + */ + const float new_scale = + (wayl_fractional_scaling(term->wl) && win->scale > 0. + ? win->scale + : (tll_length(win->on_outputs) > 0 + ? tll_back(win->on_outputs)->scale + : 1.)); + + if (new_scale == term->scale) + return false; + + LOG_DBG("scaling factor changed: %.2f -> %.2f", term->scale, new_scale); + term->scale = new_scale; + return true; +} + bool term_font_dpi_changed(struct terminal *term, float old_scale) { @@ -2099,9 +2134,9 @@ term_font_dpi_changed(struct terminal *term, float old_scale) term->font_is_sized_by_dpi = will_scale_using_dpi; if (!need_font_reload) - return true; + return false; - return reload_fonts(term); + return reload_fonts(term, false); } void @@ -3500,7 +3535,7 @@ term_update_ascii_printer(struct terminal *term) #if defined(_DEBUG) && LOG_ENABLE_DBG if (term->ascii_printer != new_printer) { - LOG_DBG("§switching ASCII printer %s -> %s", + LOG_DBG("switching ASCII printer %s -> %s", term->ascii_printer == &ascii_printer_fast ? "fast" : "generic", new_printer == &ascii_printer_fast ? "fast" : "generic"); } diff --git a/terminal.h b/terminal.h index 60d3c3ac..4b1d1d0d 100644 --- a/terminal.h +++ b/terminal.h @@ -736,6 +736,7 @@ bool term_to_slave(struct terminal *term, const void *data, size_t len); bool term_paste_data_to_slave( struct terminal *term, const void *data, size_t len); +bool term_update_scale(struct terminal *term); bool term_font_size_increase(struct terminal *term); bool term_font_size_decrease(struct terminal *term); bool term_font_size_reset(struct terminal *term); diff --git a/wayland.c b/wayland.c index 85140d6f..354a0e78 100644 --- a/wayland.c +++ b/wayland.c @@ -396,17 +396,35 @@ static const struct wl_seat_listener seat_listener = { static void update_term_for_output_change(struct terminal *term) { - if (tll_length(term->window->on_outputs) == 0) - return; + const float old_scale = term->scale; + const float logical_width = term->width / term->scale; + const float logical_height = term->height / term->scale; - float old_scale = term->scale; - - render_resize(term, - round(term->width / term->scale), - round(term->height / term->scale)); - term_font_dpi_changed(term, old_scale); + /* Note: order matters! term_update_scale() must come first */ + bool scale_updated = term_update_scale(term); + bool fonts_updated = term_font_dpi_changed(term, old_scale); term_font_subpixel_changed(term); + csd_reload_font(term->window, old_scale); + + if (fonts_updated) { + /* + * If the fonts have been updated, the cell dimensions have + * changed. This requires a “forced” resize, since the surface + * buffer dimensions may not have been updated (in which case + * render_size() normally shortcuts and returns early). + */ + render_resize_force(term, round(logical_width), round(logical_height)); + } + + else if (scale_updated) { + /* + * A scale update means the surface buffer dimensions have + * been updated, even though the window logical dimensions + * haven’t changed. + */ + render_resize(term, round(logical_width), round(logical_height)); + } } static void