emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master b18d4dbe0d 3/3: Fix automatic DPI adjustment and add workarounds


From: Po Lu
Subject: master b18d4dbe0d 3/3: Fix automatic DPI adjustment and add workarounds for some systems
Date: Sat, 19 Nov 2022 01:03:49 -0500 (EST)

branch: master
commit b18d4dbe0d64bd1277731f9a7faedbb4dd3cd197
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix automatic DPI adjustment and add workarounds for some systems
    
    * lisp/faces.el (x-create-frame-with-faces): New field
    `delayed-font'.  Set the `font-parameter' property to `font' in
    the given parameter list after face-set-after-frame-default is
    called.
    * src/fontset.c (Fset_fontset_font): Avoid changing
    `font-parameter' with the call to Fmodify_frame_parameters.
    * src/frame.c (gui_set_frame_parameters_1): New function.
    Factor out gui_set_frame_parameters here, and add an argument
    DEFAULT_PARAMETER.  If the `font' parameter is set, and
    `default_parameter' is not, then set the `font-parameter' frame
    parameter to the `font' parameter as well, to keep track of
    which user-specified `font' frame parameter set the default
    face's font on the frame.
    (gui_set_frame_parameters): Call gui_set_frame_parameters_1 with
    new arg set to false.
    (gui_set_font): Remove broken implementation of
    `font-parameter'.
    (gui_default_parameter): If the default value was used, then
    call gui_set_frame_parameters_1 with the new argument set to
    false.  This is because no font was specified as a frame
    parameter by the user, so Freconsider_frame_fonts is free to do
    anything it wants.
    (Freconsider_frame_fonts): If `font-parameter' is set, then use
    it.
    (syms_of_frame): New defsym Qfont_parameter.
    
    * src/frame.h: Update prototypes.
    
    * src/haikuterm.c (haiku_default_font_parameter):
    * src/pgtkfns.c (pgtk_default_font_parameter):
    * src/w32fns.c (w32_default_font_parameter): Stop setting
    `font-parameter' here.  This code resulted in decades of
    automatic font rescaling not working correctly.
    
    * src/xfaces.c (set_font_frame_param): Clear the
    `font-parameter' frame parameter.
    (Finternal_merge_in_global_face):
    * src/xfns.c (x_default_font_parameter): Avoid changing
    `font-parameter' in response to changes to face attributes.
    * src/xsettings.c (apply_xft_settings): Add workaround for
    Cairo.  (bug#59371, bug#59347, bug#59283, bug#59271, bug#59285,
    bug#59306.)
---
 lisp/faces.el   | 10 ++++++++
 src/fontset.c   | 12 ++++++++-
 src/frame.c     | 80 ++++++++++++++++++++++++++++++++++++++++++---------------
 src/frame.h     |  1 +
 src/haikuterm.c | 15 ++++-------
 src/pgtkfns.c   |  7 -----
 src/w32fns.c    |  8 +-----
 src/xfaces.c    | 20 ++++++++++++---
 src/xfns.c      |  7 -----
 src/xsettings.c |  8 ++++++
 10 files changed, 112 insertions(+), 56 deletions(-)

diff --git a/lisp/faces.el b/lisp/faces.el
index 5ae1c65a4d..c69339e2fd 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -2200,8 +2200,13 @@ the X resource \"reverseVideo\" is present, handle that."
                           border-color cursor-color mouse-color
                           visibility scroll-bar-foreground
                           scroll-bar-background))
+         (delayed-font nil)
         frame success)
     (dolist (param delayed-params)
+      ;; Save the font used here.  Once the frame is created, set the
+      ;; `font-parameter' frame parameter.
+      (when (and (eq param 'font) (assq 'font parameters))
+        (setq delayed-font (cdr (assq 'font parameters))))
       (setq params (assq-delete-all param params)))
     (setq frame (x-create-frame `((visibility . nil) . ,params)))
     (unwind-protect
@@ -2212,6 +2217,11 @@ the X resource \"reverseVideo\" is present, handle that."
          (x-handle-reverse-video frame parameters)
          (frame-set-background-mode frame t)
          (face-set-after-frame-default frame parameters)
+          ;; The code above will not set the `font-parameter' frame
+          ;; property, which is used by dynamic-setting.el to respect
+          ;; fonts specified by the user via frame parameters (as
+          ;; opposed to face attributes).  Set the parameter manually.
+          (set-frame-parameter frame 'font-parameter delayed-font)
           ;; Mark frame as 'was-invisible' when it was created as
           ;; invisible or iconified and PARAMETERS contains either a
           ;; width or height specification.  This should be sufficient
diff --git a/src/fontset.c b/src/fontset.c
index 4b91eff2ef..b82737d005 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -1663,7 +1663,17 @@ overwrites the previous settings.  */)
            {
              update_auto_fontset_alist (font_object, fontset_obj);
              AUTO_FRAME_ARG (arg, Qfont, Fcons (fontset, font_object));
-             Fmodify_frame_parameters (fr, arg);
+
+#ifdef HAVE_WINDOW_SYSTEM
+             if (FRAME_WINDOW_P (f))
+               /* This is a window-system frame.  Prevent changes of
+                  the `font' parameter here from messing with the
+                  `font-parameter' frame property, as the frame
+                  parameter is not being changed by the user.  */
+               gui_set_frame_parameters_1 (f, arg, true);
+             else
+#endif
+               Fmodify_frame_parameters (fr, arg);
            }
        }
     }
diff --git a/src/frame.c b/src/frame.c
index 151a402995..b57b296be5 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -4119,10 +4119,17 @@ frame_float (struct frame *f, Lisp_Object val, enum 
frame_float_type what,
    If a parameter is not specially recognized, do nothing special;
    otherwise call the `gui_set_...' function for that parameter.
    Except for certain geometry properties, always call store_frame_param
-   to store the new value in the parameter alist.  */
+   to store the new value in the parameter alist.
+
+   DEFAULT_PARAMETER should be set if the alist was not specified by
+   the user, or by the face code to set the `font' parameter.  In that
+   case, the `font-parameter' frame parameter should not be changed,
+   so dynamic-setting.el can restore the user's selected font
+   correctly.  */
 
 void
-gui_set_frame_parameters (struct frame *f, Lisp_Object alist)
+gui_set_frame_parameters_1 (struct frame *f, Lisp_Object alist,
+                           bool default_parameter)
 {
   Lisp_Object tail, frame;
 
@@ -4249,7 +4256,7 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object 
alist)
        }
       else
        {
-         register Lisp_Object param_index, old_value;
+         Lisp_Object param_index, old_value;
 
          old_value = get_frame_param (f, prop);
 
@@ -4260,6 +4267,12 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object 
alist)
              && XFIXNAT (param_index) < ARRAYELTS (frame_parms)
              && FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])
            (*(FRAME_RIF (f)->frame_parm_handlers[XFIXNUM (param_index)])) (f, 
val, old_value);
+
+         if (!default_parameter && EQ (prop, Qfont))
+           /* The user manually specified the `font' frame parameter.
+              Save that parameter for future use by the
+              dynamic-setting code.  */
+           store_frame_param (f, Qfont_parameter, val);
        }
     }
 
@@ -4410,6 +4423,11 @@ gui_set_frame_parameters (struct frame *f, Lisp_Object 
alist)
   SAFE_FREE ();
 }
 
+void
+gui_set_frame_parameters (struct frame *f, Lisp_Object alist)
+{
+  gui_set_frame_parameters_1 (f, alist, false);
+}
 
 /* Insert a description of internally-recorded parameters of frame F
    into the parameter alist *ALISTPTR that is to be given to the user.
@@ -4586,9 +4604,6 @@ gui_set_font (struct frame *f, Lisp_Object arg, 
Lisp_Object oldval)
 {
   Lisp_Object font_object;
   int fontset = -1;
-#ifdef HAVE_X_WINDOWS
-  Lisp_Object font_param = arg;
-#endif
 
   /* Set the frame parameter back to the old value because we may
      fail to use ARG as the new parameter value.  */
@@ -4627,16 +4642,10 @@ gui_set_font (struct frame *f, Lisp_Object arg, 
Lisp_Object oldval)
        error ("Unknown fontset: %s", SDATA (XCAR (arg)));
       font_object = XCDR (arg);
       arg = AREF (font_object, FONT_NAME_INDEX);
-#ifdef HAVE_X_WINDOWS
-      font_param = Ffont_get (font_object, QCname);
-#endif
     }
   else if (FONT_OBJECT_P (arg))
     {
       font_object = arg;
-#ifdef HAVE_X_WINDOWS
-      font_param = Ffont_get (font_object, QCname);
-#endif
       /* This is to store the XLFD font name in the frame parameter for
         backward compatibility.  We should store the font-object
         itself in the future.  */
@@ -4667,9 +4676,7 @@ gui_set_font (struct frame *f, Lisp_Object arg, 
Lisp_Object oldval)
   if (FRAME_TERMINAL (f)->set_new_font_hook)
     FRAME_TERMINAL (f)->set_new_font_hook (f, font_object, fontset);
   store_frame_param (f, Qfont, arg);
-#ifdef HAVE_X_WINDOWS
-  store_frame_param (f, Qfont_parameter, font_param);
-#endif
+
   /* Recalculate tabbar height.  */
   f->n_tab_bar_rows = 0;
   /* Recalculate toolbar height.  */
@@ -5451,12 +5458,20 @@ gui_default_parameter (struct frame *f, Lisp_Object 
alist, Lisp_Object prop,
                        enum resource_types type)
 {
   Lisp_Object tem;
+  bool was_unbound;
 
   tem = gui_frame_get_arg (f, alist, prop, xprop, xclass, type);
+
   if (BASE_EQ (tem, Qunbound))
-    tem = deflt;
+    {
+      tem = deflt;
+      was_unbound = true;
+    }
+  else
+    was_unbound = false;
+
   AUTO_FRAME_ARG (arg, prop, tem);
-  gui_set_frame_parameters (f, arg);
+  gui_set_frame_parameters_1 (f, arg, was_unbound);
   return tem;
 }
 
@@ -5959,16 +5974,26 @@ have changed.  */)
   (Lisp_Object frame)
 {
   struct frame *f;
-  Lisp_Object params;
+  Lisp_Object params, font_parameter;
 
   f = decode_window_system_frame (frame);
 
   /* Kludge: if a `font' parameter was already specified,
-     create an alist containing just that parameter.  (bug#59371) */
+     create an alist containing just that parameter.  (bug#59371)
+
+     This sounds so simple, right?  Well, read on below: */
   params = Qnil;
 
-  if (!NILP (get_frame_param (f, Qfont)))
-    params = list1 (Fcons (Qfont, get_frame_param (f, Qfont)));
+  /* The difference between Qfont and Qfont_parameter is that the
+     latter is not set automatically by the likes of x_new_font, and
+     implicitly as the default face is realized.  It is only set when
+     the user specifically specifies a `font' frame parameter, and is
+     cleared the moment the frame's font becomes defined by a face
+     attribute, instead of through the `font' frame parameter.  */
+  font_parameter = get_frame_param (f, Qfont_parameter);
+
+  if (!NILP (font_parameter))
+    params = list1 (Fcons (Qfont, font_parameter));
 
   /* First, call this to reinitialize any font backend specific
      stuff.  */
@@ -5976,10 +6001,22 @@ have changed.  */)
   if (FRAME_RIF (f)->default_font_parameter)
     FRAME_RIF (f)->default_font_parameter (f, params);
 
+  /* For a mysterious reason, x_default_font_parameter sets Qfont to
+     nil in the alist!  */
+
+  if (!NILP (font_parameter))
+    params = list1 (Fcons (Qfont, font_parameter));
+
   /* Now call this to apply the existing value(s) of the `default'
      face.  */
   call2 (Qface_set_after_frame_default, frame, params);
 
+  /* Restore the value of the `font-parameter' parameter, as
+     `face-set-after-frame-default' will have changed it through its
+     calls to `set-face-attribute'.  */
+  if (!NILP (font_parameter))
+    store_frame_param (f, Qfont_parameter, font_parameter);
+
   return Qnil;
 }
 
@@ -6240,6 +6277,7 @@ syms_of_frame (void)
   DEFSYM (Qiconify_top_level, "iconify-top-level");
   DEFSYM (Qmake_invisible, "make-invisible");
   DEFSYM (Quse_frame_synchronization, "use-frame-synchronization");
+  DEFSYM (Qfont_parameter, "font-parameter");
 
   {
     int i;
diff --git a/src/frame.h b/src/frame.h
index 458b6257e4..d6fd62b2ac 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1670,6 +1670,7 @@ IMAGE_OPT_FROM_ID (struct frame *f, int id)
 /* The class of this X application.  */
 #define EMACS_CLASS "Emacs"
 
+extern void gui_set_frame_parameters_1 (struct frame *, Lisp_Object, bool);
 extern void gui_set_frame_parameters (struct frame *, Lisp_Object);
 extern void gui_set_fullscreen (struct frame *, Lisp_Object, Lisp_Object);
 extern void gui_set_line_spacing (struct frame *, Lisp_Object, Lisp_Object);
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 4e32b74716..496480cbc0 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -3007,9 +3007,11 @@ haiku_default_font_parameter (struct frame *f, 
Lisp_Object parms)
     font = font_open_by_spec (f, Ffont_get_system_font ());
 
   if (NILP (font))
-      font = !NILP (font_param) ? font_param
-      : gui_display_get_arg (dpyinfo, parms, Qfont, "font", "Font",
-                             RES_TYPE_STRING);
+    font = (!NILP (font_param)
+           ? font_param
+           : gui_display_get_arg (dpyinfo, parms, Qfont,
+                                  "font", "Font",
+                                  RES_TYPE_STRING));
 
   if (! FONTP (font) && ! STRINGP (font))
     {
@@ -3029,13 +3031,6 @@ haiku_default_font_parameter (struct frame *f, 
Lisp_Object parms)
       if (NILP (font))
         error ("No suitable font was found");
     }
-  else if (!NILP (font_param))
-    {
-      /* Remember the explicit font parameter, so we can re-apply it
-         after we've applied the `default' face settings.  */
-      AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
-      gui_set_frame_parameters (f, arg);
-    }
 
   gui_default_parameter (f, parms, Qfont, font, "font", "Font",
                          RES_TYPE_STRING);
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index f370f03978..a32067af81 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1121,13 +1121,6 @@ pgtk_default_font_parameter (struct frame *f, 
Lisp_Object parms)
       if (NILP (font))
        error ("No suitable font was found");
     }
-  else if (!NILP (font_param))
-    {
-      /* Remember the explicit font parameter, so we can re-apply it after
-         we've applied the `default' face settings.  */
-      AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
-      gui_set_frame_parameters (f, arg);
-    }
 
   /* This call will make X resources override any system font setting.  */
   gui_default_parameter (f, parms, Qfont, font, "font", "Font",
diff --git a/src/w32fns.c b/src/w32fns.c
index e441665804..887e5a1f7b 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -5794,13 +5794,7 @@ w32_default_font_parameter (struct frame *f, Lisp_Object 
parms)
       if (NILP (font))
        error ("No suitable font was found");
     }
-  else if (!NILP (font_param))
-    {
-      /* Remember the explicit font parameter, so we can re-apply it after
-        we've applied the `default' face settings.  */
-      gui_set_frame_parameters (f, Fcons (Fcons (Qfont_parameter, font_param),
-                                          Qnil));
-    }
+
   gui_default_parameter (f, parms, Qfont, font, "font", "Font", 
RES_TYPE_STRING);
 }
 
diff --git a/src/xfaces.c b/src/xfaces.c
index ed76db9adb..df078227c8 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -3809,8 +3809,12 @@ set_font_frame_param (Lisp_Object frame, Lisp_Object 
lface)
          ASET (lface, LFACE_FONT_INDEX, font);
        }
       f->default_face_done_p = false;
-      AUTO_FRAME_ARG (arg, Qfont, font);
-      Fmodify_frame_parameters (frame, arg);
+      AUTO_LIST2 (arg, AUTO_CONS_EXPR (Qfont, font),
+                 /* Clear the `font-parameter' frame property, as the
+                    font is now being specified by a face, not a
+                    frame property.  */
+                 AUTO_CONS_EXPR (Qfont_parameter, Qnil));
+      gui_set_frame_parameters_1 (f, arg, true);
     }
 }
 
@@ -4208,7 +4212,17 @@ Default face attributes override any local face 
attributes.  */)
            {
              Lisp_Object name = newface->font->props[FONT_NAME_INDEX];
              AUTO_FRAME_ARG (arg, Qfont, name);
-             Fmodify_frame_parameters (frame, arg);
+
+#ifdef HAVE_WINDOW_SYSTEM
+             if (FRAME_WINDOW_P (f))
+               /* This is a window-system frame.  Prevent changes of
+                  the `font' parameter here from messing with the
+                  `font-parameter' frame property, as the frame
+                  parameter is not being changed by the user.  */
+               gui_set_frame_parameters_1 (f, arg, true);
+             else
+#endif
+               Fmodify_frame_parameters (frame, arg);
            }
 
          if (STRINGP (gvec[LFACE_FOREGROUND_INDEX]))
diff --git a/src/xfns.c b/src/xfns.c
index 8ee26d713a..2ff70f7985 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -4551,13 +4551,6 @@ x_default_font_parameter (struct frame *f, Lisp_Object 
parms)
       if (NILP (font))
        error ("No suitable font was found");
     }
-  else if (!NILP (font_param))
-    {
-      /* Remember the explicit font parameter, so we can re-apply it after
-        we've applied the `default' face settings.  */
-      AUTO_FRAME_ARG (arg, Qfont_parameter, font_param);
-      gui_set_frame_parameters (f, arg);
-    }
 
   /* This call will make X resources override any system font setting.  */
   gui_default_parameter (f, parms, Qfont, font, "font", "Font", 
RES_TYPE_STRING);
diff --git a/src/xsettings.c b/src/xsettings.c
index 1a9f1a8d5a..f1ee84a1a0 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -886,6 +886,14 @@ apply_xft_settings (Display_Info *dpyinfo,
     }
 #endif
 
+#ifdef USE_CAIRO
+  /* When Cairo is being used, set oldsettings.dpi to dpyinfo->resx.
+     This is a gross hack, but seeing as Cairo fails to report
+     anything reasonable, just use it to avoid config-changed events
+     being sent at startup.  */
+  oldsettings.dpi = dpyinfo->resx;
+#endif
+
   if ((settings->seen & SEEN_DPI) != 0
       && settings->dpi > 0
       /* The following conjunct avoids setting `changed' to true when



reply via email to

[Prev in Thread] Current Thread [Next in Thread]