diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c98fdba..bbb75f1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,8 @@ * Crash when a **pipe-visible** or **pipe-scrollback** command contained an unclosed quote (https://codeberg.org/dnkl/foot/issues/49). +* Improved font size consistency across multiple monitors with + different DPI (https://codeberg.org/dnkl/foot/issues/47). ### Contributors diff --git a/terminal.c b/terminal.c index f1b528fb..81592710 100644 --- a/terminal.c +++ b/terminal.c @@ -559,7 +559,7 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4]) return true; } -static unsigned +static float get_font_dpi(const struct terminal *term) { /* @@ -584,24 +584,24 @@ get_font_dpi(const struct terminal *term) */ /* Use highest DPI from outputs we're mapped on */ - unsigned dpi = 0; + double dpi = 0.0; assert(term->window != NULL); tll_foreach(term->window->on_outputs, it) { - if (it->item->ppi.scaled.y > dpi) - dpi = it->item->ppi.scaled.y * term->scale; + if (it->item->dpi > dpi) + dpi = it->item->dpi; } /* If we're not mapped, use DPI from first monitor. Hopefully this is where we'll get mapped later... */ - if (dpi == 0) { + if (dpi == 0.) { tll_foreach(term->wl->monitors, it) { - dpi = it->item.ppi.scaled.y * term->scale; + dpi = it->item.dpi; break; } } if (dpi == 0) { /* No monitors? */ - dpi = 96; + dpi = 96.; } return dpi; @@ -692,10 +692,10 @@ reload_fonts(struct terminal *term) } char attrs0[256], attrs1[256], attrs2[256], attrs3[256]; - snprintf(attrs0, sizeof(attrs0), "dpi=%u", term->font_dpi); - snprintf(attrs1, sizeof(attrs1), "dpi=%u:weight=bold", term->font_dpi); - snprintf(attrs2, sizeof(attrs2), "dpi=%u:slant=italic", term->font_dpi); - snprintf(attrs3, sizeof(attrs3), "dpi=%u:weight=bold:slant=italic", term->font_dpi); + snprintf(attrs0, sizeof(attrs0), "dpi=%.2f", term->font_dpi); + snprintf(attrs1, sizeof(attrs1), "dpi=%.2f:weight=bold", term->font_dpi); + snprintf(attrs2, sizeof(attrs2), "dpi=%.2f:slant=italic", term->font_dpi); + snprintf(attrs3, sizeof(attrs3), "dpi=%.2f:weight=bold:slant=italic", term->font_dpi); struct fcft_font *fonts[4]; struct font_load_data data[4] = { @@ -836,7 +836,7 @@ term_init(const struct config *conf, struct fdm *fdm, struct reaper *reaper, .ptmx = ptmx, .ptmx_buffer = tll_init(), .font_sizes = malloc(sizeof(term->font_sizes[0]) * tll_length(conf->fonts)), - .font_dpi = 0, + .font_dpi = 0., .font_subpixel = (conf->colors.alpha == 0xffff /* Can't do subpixel rendering on transparent background */ ? FCFT_SUBPIXEL_DEFAULT : FCFT_SUBPIXEL_NONE), @@ -1490,11 +1490,11 @@ term_font_size_reset(struct terminal *term) bool term_font_dpi_changed(struct terminal *term) { - unsigned dpi = get_font_dpi(term); + float dpi = get_font_dpi(term); if (dpi == term->font_dpi) return true; - LOG_DBG("DPI changed (%u -> %u): reloading fonts", term->font_dpi, dpi); + LOG_DBG("DPI changed (%.2f -> %.2f): reloading fonts", term->font_dpi, dpi); term->font_dpi = dpi; return reload_fonts(term); diff --git a/terminal.h b/terminal.h index eae636cc..31316e37 100644 --- a/terminal.h +++ b/terminal.h @@ -224,7 +224,7 @@ struct terminal { struct fcft_font *fonts[4]; struct config_font *font_sizes; - int font_dpi; + float font_dpi; enum fcft_subpixel font_subpixel; tll(struct ptmx_buffer) ptmx_buffer; diff --git a/wayland.c b/wayland.c index 66f2c3b3..4dca5ef5 100644 --- a/wayland.c +++ b/wayland.c @@ -294,11 +294,18 @@ output_update_ppi(struct monitor *mon) int x_inches = mon->dim.mm.width * 0.03937008; int y_inches = mon->dim.mm.height * 0.03937008; + mon->ppi.real.x = mon->dim.px_real.width / x_inches; mon->ppi.real.y = mon->dim.px_real.height / y_inches; mon->ppi.scaled.x = mon->dim.px_scaled.width / x_inches; mon->ppi.scaled.y = mon->dim.px_scaled.height / y_inches; + + float px_diag = sqrt( + pow(mon->dim.px_scaled.width, 2) + + pow(mon->dim.px_scaled.height, 2)); + + mon->dpi = px_diag / mon->inch * mon->scale; } static void @@ -343,6 +350,7 @@ output_scale(void *data, struct wl_output *wl_output, int32_t factor) { struct monitor *mon = data; mon->scale = factor; + output_update_ppi(mon); } static const struct wl_output_listener output_listener = { @@ -1029,13 +1037,14 @@ wayl_init(const struct config *conf, struct fdm *fdm) tll_foreach(wayl->monitors, it) { LOG_INFO( - "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d PPI=%dx%d (physical) PPI=%dx%d (logical)", + "%s: %dx%d+%dx%d@%dHz %s %.2f\" scale=%d PPI=%dx%d (physical) PPI=%dx%d (logical), DPI=%.2f", it->item.name, it->item.dim.px_real.width, it->item.dim.px_real.height, it->item.x, it->item.y, (int)round(it->item.refresh), it->item.model != NULL ? it->item.model : it->item.description, it->item.inch, it->item.scale, it->item.ppi.real.x, it->item.ppi.real.y, - it->item.ppi.scaled.x, it->item.ppi.scaled.y); + it->item.ppi.scaled.x, it->item.ppi.scaled.y, + it->item.dpi); } wayl->fd = wl_display_get_fd(wayl->display); diff --git a/wayland.h b/wayland.h index e67d514a..3c39fe5d 100644 --- a/wayland.h +++ b/wayland.h @@ -236,6 +236,8 @@ struct monitor { } scaled; } ppi; + float dpi; + int scale; float refresh; enum wl_output_subpixel subpixel;