term: stash last known DPI, and use after a unmapped/mapped sequence

A compositor may unmap, and then remap the window, for example when
the window is minimized, or if the user switches workspace.

With DPI aware rendering, we *need* to know on which output we're
mapped, in order to use the correct DPI. This means the first frame we
render, before being mapped, always guesses the DPI.

In an unmap/map sequence, guessing the wrong DPI means the window will
flicker.

Fix by stashing the last used DPI value, and use that instead of
guessing.

This means the *only* time we _actually_ guess the DPI, is the very
first frame, when starting up foot.
This commit is contained in:
Daniel Eklöf 2024-04-17 08:35:58 +02:00
parent a5b369ede4
commit 7c20fb247c
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 25 additions and 3 deletions

View file

@ -68,6 +68,9 @@
* Crash when printing double-width (or longer) characters to, or near,
the last column, when auto-wrap (private mode 7) has been disabled.
* Dynamically sized sixel being trimmed to nothing.
* Flickering with `dpi-aware=yes` and window is unmapped/remapped
(some compositors do this when window is minimized), in a
multi-monitor setup with different monitor DPIs.
### Security

View file

@ -858,9 +858,25 @@ get_font_dpi(const struct terminal *term)
xassert(tll_length(term->wl->monitors) > 0);
const struct wl_window *win = term->window;
const struct monitor *mon = tll_length(win->on_outputs) > 0
? tll_back(win->on_outputs)
: &tll_front(term->wl->monitors);
const struct monitor *mon = NULL;
if (tll_length(win->on_outputs) > 0)
mon = tll_back(win->on_outputs);
else {
if (term->font_dpi_before_unmap > 0.) {
/*
* Use last known "good" DPI
*
* This avoids flickering when window is unmapped/mapped
* (some compositors do this when a window is minimized),
* on a multi-monitor setup with different monitor DPIs.
*/
return term->font_dpi_before_unmap;
}
if (tll_length(term->wl->monitors) > 0)
mon = &tll_front(term->wl->monitors);
}
if (term_fractional_scaling(term))
return mon != NULL ? mon->dpi.physical : 96.;
@ -1182,6 +1198,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper,
xmalloc(sizeof(term->font_sizes[3][0]) * conf->fonts[3].count),
},
.font_dpi = 0.,
.font_dpi_before_unmap = -1.,
.font_subpixel = (conf->colors.alpha == 0xffff /* Can't do subpixel rendering on transparent background */
? FCFT_SUBPIXEL_DEFAULT
: FCFT_SUBPIXEL_NONE),
@ -2250,6 +2267,7 @@ term_font_dpi_changed(struct terminal *term, float old_scale)
}
term->font_dpi = dpi;
term->font_dpi_before_unmap = dpi;
term->font_is_sized_by_dpi = will_scale_using_dpi;
if (!need_font_reload)

View file

@ -406,6 +406,7 @@ struct terminal {
struct config_font *font_sizes[4];
struct pt_or_px font_line_height;
float font_dpi;
float font_dpi_before_unmap;
bool font_is_sized_by_dpi;
int16_t font_x_ofs;
int16_t font_y_ofs;