diff --git a/CHANGELOG.md b/CHANGELOG.md index d229c4ec..c08b29c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,9 @@ still exported, like before. * The default install location for the terminfo definitions have been changed back to `${datadir}/terminfo`. +* `dpi-aware=auto`: fonts are now scaled using the monitor’s DPI only + when **all** monitors have a scaling factor of one + (https://codeberg.org/dnkl/foot/issues/714). ### Deprecated diff --git a/README.md b/README.md index 93d783c4..d90302f8 100644 --- a/README.md +++ b/README.md @@ -347,9 +347,9 @@ This is not how it is meant to be. Fonts are measured in _point sizes_ 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 monitors where output scaling has -been enabled, fonts will instead be sized using the scaling -factor. +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. This can be changed to either **always** use the monitor’s DPI (regardless of scaling factor), or to **never** use it, with the diff --git a/box-drawing.c b/box-drawing.c index 887aa0c9..3f8a38ef 100644 --- a/box-drawing.c +++ b/box-drawing.c @@ -2837,8 +2837,8 @@ box_drawing(const struct terminal *term, wchar_t wc) abort(); } - double dpi = term_font_sized_by_dpi(term, term->scale) ? term->font_dpi : 96.; - double scale = term_font_sized_by_scale(term, term->scale) ? term->scale : 1.; + double dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.; + double scale = term->font_is_sized_by_dpi ? 1. : term->scale; double cell_size = sqrt(pow(term->cell_width, 2) + pow(term->cell_height, 2)); int base_thickness = diff --git a/doc/foot.ini.5.scd b/doc/foot.ini.5.scd index ea4779c5..6bc93cc4 100644 --- a/doc/foot.ini.5.scd +++ b/doc/foot.ini.5.scd @@ -161,8 +161,10 @@ in this order: scaling factor *does* double the font size. Finally, if set to *auto*, fonts will be sized using the monitor's - DPI on monitors with a scaling factor of 1, but otherwise using - the scaling factor. + 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 diff --git a/terminal.c b/terminal.c index e6837977..2738291d 100644 --- a/terminal.c +++ b/terminal.c @@ -813,25 +813,48 @@ get_font_subpixel(const struct terminal *term) return FCFT_SUBPIXEL_DEFAULT; } -bool -term_font_sized_by_dpi(const struct terminal *term, int scale) +static bool +term_font_size_by_dpi(const struct terminal *term) { - return term->conf->dpi_aware == DPI_AWARE_YES || - (term->conf->dpi_aware == DPI_AWARE_AUTO && scale <= 1); -} + switch (term->conf->dpi_aware) { + case DPI_AWARE_YES: return true; + case DPI_AWARE_NO: return false; -bool -term_font_sized_by_scale(const struct terminal *term, int scale) -{ - return !term_font_sized_by_dpi(term, scale); + 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) { - double scale = term_font_sized_by_scale(term, term->scale) ? term->scale : 1.; - double dpi = term_font_sized_by_dpi(term, term->scale) ? term->font_dpi : 96.; + double scale = !term->font_is_sized_by_dpi ? term->scale : 1.; + double dpi = term->font_is_sized_by_dpi ? term->font_dpi : 96.; return pt_or_px->px == 0 ? round(pt_or_px->pt * scale * dpi / 72) @@ -878,8 +901,7 @@ 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_sized_by_scale(term, term->scale) ? term->scale : 1; + const int scale = term->font_is_sized_by_dpi ? 1 : term->scale; if (use_px_size) snprintf(size, sizeof(size), ":pixelsize=%d", @@ -914,7 +936,7 @@ reload_fonts(struct terminal *term) const size_t count_bold_italic = custom_bold_italic ? counts[3] : counts[0]; const char **names_bold_italic = (const char **)(custom_bold_italic ? names[3] : names[0]); - const bool use_dpi = term_font_sized_by_dpi(term, term->scale); + const bool use_dpi = term->font_is_sized_by_dpi; char *attrs[4] = {NULL}; int attr_len[4] = {-1, -1, -1, -1}; /* -1, so that +1 (below) results in 0 */ @@ -2008,8 +2030,8 @@ term_font_dpi_changed(struct terminal *term, int old_scale) float dpi = get_font_dpi(term); xassert(term->scale > 0); - bool was_scaled_using_dpi = term_font_sized_by_dpi(term, old_scale); - bool will_scale_using_dpi = term_font_sized_by_dpi(term, term->scale); + bool was_scaled_using_dpi = term->font_is_sized_by_dpi; + bool will_scale_using_dpi = term_font_size_by_dpi(term); bool need_font_reload = was_scaled_using_dpi != will_scale_using_dpi || @@ -2019,15 +2041,16 @@ term_font_dpi_changed(struct terminal *term, int old_scale) if (need_font_reload) { LOG_DBG("DPI/scale change: DPI-awareness=%s, " - "DPI: %.2f -> %.2f, scale: %d, " + "DPI: %.2f -> %.2f, scale: %d -> %d, " "sizing font based on monitor's %s", term->conf->dpi_aware == DPI_AWARE_AUTO ? "auto" : term->conf->dpi_aware == DPI_AWARE_YES ? "yes" : "no", - term->font_dpi, dpi, term->scale, + term->font_dpi, dpi, old_scale, term->scale, will_scale_using_dpi ? "DPI" : "scaling factor"); } term->font_dpi = dpi; + term->font_is_sized_by_dpi = will_scale_using_dpi; if (!need_font_reload) return true; diff --git a/terminal.h b/terminal.h index 028b4844..b3b4a90e 100644 --- a/terminal.h +++ b/terminal.h @@ -329,6 +329,7 @@ struct terminal { struct config_font *font_sizes[4]; struct pt_or_px font_line_height; float font_dpi; + bool font_is_sized_by_dpi; int16_t font_x_ofs; int16_t font_y_ofs; enum fcft_subpixel font_subpixel; @@ -660,8 +661,6 @@ bool term_font_size_reset(struct terminal *term); bool term_font_dpi_changed(struct terminal *term, int old_scale); void term_font_subpixel_changed(struct terminal *term); -bool term_font_sized_by_dpi(const struct terminal *term, int scale); -bool term_font_sized_by_scale(const struct terminal *term, int scale); int term_pt_or_px_as_pixels( const struct terminal *term, const struct pt_or_px *pt_or_px); diff --git a/wayland.c b/wayland.c index 911694ff..49c8ed92 100644 --- a/wayland.c +++ b/wayland.c @@ -340,6 +340,11 @@ 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);