Subject: bug#39865: 28.0.50; Emacs crash

From: Robert Pluim <[email-masked]>
Date: Tue, 17 Mar 2020 11:16:34 +0100

>>>>> On Fri, 13 Mar 2020 16:09:25 +0100, Robert Pluim <[email-masked]> said:
    Eli> ... this is not how we introduce terminal-dependent methods.  We don't
    Eli> define different versions of gui_SOMETHING functions in each
    Eli> terminal-specific back-end.  Instead, we add a member to 'struct
    Eli> redisplay_interface', and then assign a different value to it in each
    Eli> back-end.  See how x_redisplay_interface, w32_redisplay_interface,
    Eli> etc. are defined in the respective *term.[cm] files, and how they are
    Eli> used via the FRAME_RIF macro.

    Robert> OK, I can rework it using that.

The following has been compiled and tested on macOS, GNU/Linux, and
MSWindows. Itʼs against emacs-27, where Iʼd prefer to put it, since
people might start building that with Cairo enabled, which would make
this crash more likely, but I can put it in master if you wish.

Robert

>From 6c1062b32f760bf220477230bb1e41a6c7149f2b Mon Sep 17 00:00:00 2001
From: Robert Pluim <[email-masked]>
Date: Mon, 16 Mar 2020 17:21:02 +0100
Subject: [PATCH] Recalculate default font when switching font backend
To: [email-masked]

This is an updated version of the patch by Dmitry Antipov
<[email-masked]> in
<https://debbugs.gnu.org/cgi/bugreport.cgi?bug=23386#43>.

Fixes Bug#23386

* src/dispextern.h (struct redisplay_interface): New member
default_font_parameter.
* src/xterm.h: Add prototype for x_default_font_parameter.
* src/xterm.c (x_redisplay_interface): Initialize
default_font_parameter member.
* src/xfns.c (x_default_font_parameter): Make non-static.
* src/w32term.h: Add prototype for w32_default_font_parameter
* src/w32fns.c (w32_default_font_parameter): Make non-static.
* src/w32term.c (w32_redisplay_interface): Initialize
default_font_parameter member.
* src/nsterm.m (ns_redisplay_interface): Add dummy
ns_default_font_parameter (there is currently only one possible font
backend on macOS).  Initialize default_font_parameter member.
* src/frame.c (gui_set_font_backend): Recalculate default font using
RIF default_font_parameter to avoid crash when changing font backend.
---
 src/dispextern.h |  3 +++
 src/frame.c      | 12 +++++++-----
 src/nsterm.m     | 10 +++++++++-
 src/w32fns.c     |  2 +-
 src/w32term.c    |  3 ++-
 src/w32term.h    |  4 ++++
 src/xfns.c       |  2 +-
 src/xterm.c      |  3 ++-
 src/xterm.h      |  1 +
 9 files changed, 30 insertions(+), 10 deletions(-)

diff --git a/src/dispextern.h b/src/dispextern.h
index 6246c7c080..724aad4227 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3003,6 +3003,9 @@ reset_mouse_highlight (Mouse_HLInfo *hlinfo)
   /* Cancel hourglass cursor on frame F.  */
   void (*hide_hourglass) (struct frame *f);
 
+  /* Called to (re)calculate the default face when changing the font
+     backend.  */
+  void (*default_font_parameter) (struct frame *f, Lisp_Object parms);
 #endif /* HAVE_WINDOW_SYSTEM */
 };
 
diff --git a/src/frame.c b/src/frame.c
index 88d6f22fc0..ecf175f4f9 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -4565,7 +4565,11 @@ gui_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_va
     return;
 
   if (FRAME_FONT (f))
-    free_all_realized_faces (Qnil);
+    {
+      Lisp_Object frame;
+      XSETFRAME (frame, f);
+      free_all_realized_faces (frame);
+    }
 
   new_value = font_update_drivers (f, NILP (new_value) ? Qt : new_value);
   if (NILP (new_value))
@@ -4579,10 +4583,8 @@ gui_set_font_backend (struct frame *f, Lisp_Object new_value, Lisp_Object old_va
 
   if (FRAME_FONT (f))
     {
-      Lisp_Object frame;
-
-      XSETFRAME (frame, f);
-      gui_set_font (f, Fframe_parameter (frame, Qfont), Qnil);
+      /* Reconsider default font after backend(s) change (Bug#23386).  */
+      FRAME_RIF(f)->default_font_parameter (f, Qnil);
       face_change = true;
       windows_or_buffers_changed = 18;
     }
diff --git a/src/nsterm.m b/src/nsterm.m
index ed2d82ceae..e92e3d5a6f 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -5132,6 +5132,13 @@ static Lisp_Object ns_string_to_lispmod (const char *s)
     reset_mouse_highlight (&dpyinfo->mouse_highlight);
 }
 
+/* This currently does nothing, since it's only really needed when
+   changing the font-backend, but macOS currently only has one
+   possible backend.  This may change if we add HarfBuzz support.  */
+static void
+ns_default_font_parameter (struct frame *f, Lisp_Object parms)
+{
+}
 
 /* This and next define (many of the) public functions in this file.  */
 /* gui_* are generic versions in xdisp.c that we, and other terms, get away
@@ -5167,7 +5174,8 @@ static Lisp_Object ns_string_to_lispmod (const char *s)
   ns_draw_window_divider,
   ns_shift_glyphs_for_insert,
   ns_show_hourglass,
-  ns_hide_hourglass
+  ns_hide_hourglass,
+  ns_default_font_parameter
 };

diff --git a/src/w32fns.c b/src/w32fns.c
index 61e22e5700..2f01fb52e9 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -5749,7 +5749,7 @@ do_unwind_create_frame (Lisp_Object frame)
   unwind_create_frame (frame);
 }
 
-static void
+void
 w32_default_font_parameter (struct frame *f, Lisp_Object parms)
 {
   struct w32_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
diff --git a/src/w32term.c b/src/w32term.c
index f515f5604d..76cf6bd696 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -7249,7 +7249,8 @@ w32_make_rdb (char *xrm_option)
   w32_draw_window_divider,
   w32_shift_glyphs_for_insert,
   w32_show_hourglass,
-  w32_hide_hourglass
+  w32_hide_hourglass,
+  w32_default_font_parameter
 };
 
 static void w32_delete_terminal (struct terminal *term);
diff --git a/src/w32term.h b/src/w32term.h
index 737764b894..f8a8a727e8 100644
--- a/src/w32term.h
+++ b/src/w32term.h
@@ -267,6 +267,10 @@ #define CP_DEFAULT 1004
 extern const char *w32_get_string_resource (void *v_rdb,
                                             const char *name,
                                             const char *class);
+
+/* w32fns.c */
+extern void w32_default_font_parameter (struct frame* f, Lisp_Object parms);
+
 
 #define PIX_TYPE COLORREF
 
diff --git a/src/xfns.c b/src/xfns.c
index 276ea1c393..afe1ceef81 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -3555,7 +3555,7 @@ do_unwind_create_frame (Lisp_Object frame)
   unwind_create_frame (frame);
 }
 
-static void
+void
 x_default_font_parameter (struct frame *f, Lisp_Object parms)
 {
   struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
diff --git a/src/xterm.c b/src/xterm.c
index 21d99f0c7b..2ba3c00940 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -13374,7 +13374,8 @@ x_activate_timeout_atimer (void)
     x_draw_window_divider,
     x_shift_glyphs_for_insert, /* Never called; see comment in function.  */
     x_show_hourglass,
-    x_hide_hourglass
+    x_hide_hourglass,
+    x_default_font_parameter
   };

diff --git a/src/xterm.h b/src/xterm.h
index 51e75890b6..bc10043c54 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -1056,6 +1056,7 @@ #define SELECTION_EVENT_TIME(eventp)	\
                                     int *xptr,
                                     int *yptr,
                                     int *outer_border);
+extern void x_default_font_parameter (struct frame* f, Lisp_Object parms);
 
 /* From xrdb.c.  */
 
-- 
2.25.0.232.gd8437c57fa