From 293be04298e91b0b0a86230df60e72346da9987f Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 13 Jan 2025 20:47:01 +0000 Subject: [PATCH] GTK: cherry-pick font defaults and fallbacks from main. This is a combined cherry-pick of three consecutive commits from main: b088d77d580b8f7 GTK: hard-code some last-ditch fallback fonts. 7f4cccde2ae53c0 GTK: fixes to the previous font fallback patch. 6155365076c47a8 GTK: switch the default to client-side fonts. The combined effect is that now PuTTY's built-in default font is client-side rather than server-side (advantaging Wayland and disadvantaging legacy GTK1 builds, which seems like a sensible tradeoff these days), and also, if the configured main font can't be found, we'll try falling back to either the client- or server-side default (whichever is available) before giving up completely and whinging on standard error. --- unix/platform.h | 22 ++++++++++++----- unix/window.c | 65 +++++++++++++++++++++++++++++++++++++------------ 2 files changed, 65 insertions(+), 22 deletions(-) diff --git a/unix/platform.h b/unix/platform.h index 670febd7..fb3629ee 100644 --- a/unix/platform.h +++ b/unix/platform.h @@ -394,13 +394,23 @@ void setup_fd_socket(Socket *s, int infd, int outfd, int inerrfd); void fd_socket_set_psb_prefix(Socket *s, const char *prefix); /* - * Default font setting, which can vary depending on NOT_X_WINDOWS. + * Default font settings. We have a default font for each of + * client-side and server-side, so that we can use one of each as a + * fallback, and we also have a single overall default which goes into + * Conf to populate the initial state of Default Settings. + * + * In the past, this default varied with NOT_X_WINDOWS. But these days + * non-X11 environments like Wayland with only client-side fonts are + * common, and even an X11-capable _build_ of PuTTY is quite likely to + * find out at run time that X11 and its bitmap fonts aren't + * available. Also, a fixed-size bitmap font doesn't play nicely with + * high-DPI displays. And the GTK1 build of PuTTY, which can _only_ + * handle server-side fonts, is legacy. So the default font is + * unconditionally the client-side one. */ -#ifdef NOT_X_WINDOWS -#define DEFAULT_GTK_FONT "client:Monospace 12" -#else -#define DEFAULT_GTK_FONT "server:fixed" -#endif +#define DEFAULT_GTK_CLIENT_FONT "client:Monospace 12" +#define DEFAULT_GTK_SERVER_FONT "server:fixed" +#define DEFAULT_GTK_FONT DEFAULT_GTK_CLIENT_FONT /* * pty.c. diff --git a/unix/window.c b/unix/window.c index 97977c3c..7302dc2c 100644 --- a/unix/window.c +++ b/unix/window.c @@ -4368,22 +4368,22 @@ static bool gtk_seat_get_windowid(Seat *seat, long *id) } #endif -char *setup_fonts_ucs(GtkFrontend *inst) +char *setup_fonts_ucs(GtkFrontend *inst, Conf *conf) { - bool shadowbold = conf_get_bool(inst->conf, CONF_shadowbold); - int shadowboldoffset = conf_get_int(inst->conf, CONF_shadowboldoffset); + bool shadowbold = conf_get_bool(conf, CONF_shadowbold); + int shadowboldoffset = conf_get_int(conf, CONF_shadowboldoffset); FontSpec *fs; unifont *fonts[4]; int i; - fs = conf_get_fontspec(inst->conf, CONF_font); + fs = conf_get_fontspec(conf, CONF_font); fonts[0] = multifont_create(inst->area, fs->name, false, false, shadowboldoffset, shadowbold); if (!fonts[0]) { return dupprintf("unable to load font \"%s\"", fs->name); } - fs = conf_get_fontspec(inst->conf, CONF_boldfont); + fs = conf_get_fontspec(conf, CONF_boldfont); if (shadowbold || !fs->name[0]) { fonts[1] = NULL; } else { @@ -4396,7 +4396,7 @@ char *setup_fonts_ucs(GtkFrontend *inst) } } - fs = conf_get_fontspec(inst->conf, CONF_widefont); + fs = conf_get_fontspec(conf, CONF_widefont); if (fs->name[0]) { fonts[2] = multifont_create(inst->area, fs->name, true, false, shadowboldoffset, shadowbold); @@ -4410,7 +4410,7 @@ char *setup_fonts_ucs(GtkFrontend *inst) fonts[2] = NULL; } - fs = conf_get_fontspec(inst->conf, CONF_wideboldfont); + fs = conf_get_fontspec(conf, CONF_wideboldfont); if (shadowbold || !fs->name[0]) { fonts[3] = NULL; } else { @@ -4861,7 +4861,7 @@ static void after_change_settings_dialog(void *vctx, int retval) conf_get_bool(newconf, CONF_shadowbold) || conf_get_int(oldconf, CONF_shadowboldoffset) != conf_get_int(newconf, CONF_shadowboldoffset)) { - char *errmsg = setup_fonts_ucs(inst); + char *errmsg = setup_fonts_ucs(inst, inst->conf); if (errmsg) { char *msgboxtext = dupprintf("Could not change fonts in terminal window: %s\n", @@ -4950,7 +4950,7 @@ static void change_font_size(GtkFrontend *inst, int increment) } } - errmsg = setup_fonts_ucs(inst); + errmsg = setup_fonts_ucs(inst, inst->conf); if (errmsg) goto cleanup; @@ -5350,15 +5350,48 @@ void new_session_window(Conf *conf, const char *geometry_string) inst->area = gtk_drawing_area_new(); gtk_widget_set_name(GTK_WIDGET(inst->area), "drawing-area"); + /* + * Try to create the fonts for use in the window. If this fails, + * we'll try again with some fallback settings, and only abort + * completely if we can't find any fonts at all. + */ { - char *errmsg = setup_fonts_ucs(inst); - if (errmsg) { - window_setup_error(errmsg); - sfree(errmsg); - gtk_widget_destroy(inst->area); - sfree(inst); - return; + char *errmsg_main = setup_fonts_ucs(inst, inst->conf); + if (!errmsg_main) + goto fonts_ok; + + static const char *const fallbacks[] = { + DEFAULT_GTK_CLIENT_FONT, + DEFAULT_GTK_SERVER_FONT, + }; + for (size_t i = 0; i < lenof(fallbacks); i++) { + Conf *fallback_conf = conf_new(); + do_defaults(NULL, fallback_conf); + + FontSpec *fs = fontspec_new(fallbacks[i]); + conf_set_fontspec(fallback_conf, CONF_font, fs); + fontspec_free(fs); + + char *errmsg_fallback = setup_fonts_ucs(inst, fallback_conf); + conf_free(fallback_conf); + + if (!errmsg_fallback) { + fprintf(stderr, "%s; falling back to default font '%s'\n", + errmsg_main, fallbacks[i]); + sfree(errmsg_main); + goto fonts_ok; + } + + sfree(errmsg_fallback); } + + window_setup_error(errmsg_main); + sfree(errmsg_main); + gtk_widget_destroy(inst->area); + sfree(inst); + return; + + fonts_ok:; } #if GTK_CHECK_VERSION(2,0,0)