Subject: Re: bug#60585: 30.0.50; global-text-scale-adjust shrinks window (was not before), was: Re: bug#52493: 29.0.50; Setting Inconsolata up in init.el makes default face rendered wrong

From: martin rudalics <[email-masked]>
Date: Mon, 13 Feb 2023 11:09:05 +0100

>>  > The end of *foo* for GTK3 contains:
 >>  >
 >>  > xg_frame_resized old native pixels 1488x1296 new native pixels 1488x1346
 >>  > xg_frame_resized old native pixels 1488x1296 new native pixels 1488x1296
 >>  > xg_wm_set_size_hint scale 2 char width 18 toolbar 0 vscroll 32 fringes 16 borders 0 text width 720 base width 33 width inc 9
 >>  >      char height 36 menubar 50 toolbar 0 hscroll 0 borders 0 text height 648 base height 43 height inc 18
 >>  > xg_wm_set_size_hint scale 2 char width 18 toolbar 0 vscroll 32 fringes 16 borders 0 text width 720 base width 33 width inc 9
 >>  >      char height 36 menubar 50 toolbar 82 hscroll 0 borders 0 text height 648 base height 84 height inc 18
 >>  > xg_frame_set_char_size old native pixels 1488x1296 new native pixels 1488x1296 outer pixels 744x714 outer rest 0x0
 >>  >      base_size 33x84 size increments 9x18 WM hint 79x35
 >>
 >> Can you show me the text pixels values?  These are the ones we should
 >> compare.  The native values differ because for Lucid the height includes
 >> the toolbar which we draw ourselves into the rectangle the WM allots to
 >> us.  GTK draws the toolbar into its own area which is outside the native
 >> rectangle.
 >
 > How do I get that numbers?

It's what in *foo* should appear after "new text pixels".

 >>  > And for Lucid, it contains:
 >>  >
 >>  > EmacsFrameResize old native pixels 1474x1332 new native pixels 1474x1354
 >>  > EmacsFrameResize old native pixels 1474x1332 new native pixels 1474x1354
 >>  > adjust_frame_size old native pixels 1474x1332 new native pixels 1474x1354 old text pixels 1440x1296 new text pixels 1440x1296 old text chars 80x36 new text chars 80x36
 >>
 >> Here I would have liked to see the value for the scroll bar - vscroll.
 >> I suppose these differ on Lucid and GTK.

That's what in *foo* should appear after "vscroll".

 >>  > Lucid's menu bar and tool bar look shorter in height, with less padding. The font size seems to be equal, however.
 >>
 >> When you put the two frames side by side, does the text area start lower
 >> with GTK?  Here they start at exactly the same pixel position.  I attach
 >> a screenshot so you can see.
 >
 > It does. See the attached screenshots with unpatched builds.

I see.  BTW, your Lucid scroll bar doesn't seem to have a ruler (or
thumb, or whatever you call it) nor the arrows at top and bottom.

 > I think the above means that x_new_font is called for the second time even in the Lucid build. Anyway, with GNOME and the patch:
 >
 > It is hit twice, and both calls seems to have the same backtrace.
 >
 > (gdb) xbacktrace
 > "internal-set-lisp-face-attribute" (0xf09ff218)
 > "set-face-attribute" (0xffffd8c0)
 > "progn" (0xffffda70)
 > "eval" (0xf09ff180)
 > "elisp--eval-last-sexp" (0xf09ff100)
 > "eval-last-sexp" (0xffffdc50)
 > "funcall-interactively" (0xffffdc48)
 > "call-interactively" (0xf09ff070)
 > "command-execute" (0xffffdef8)
 >
 > and
 >
 > (gdb) backtrace
 > #0  x_new_font (f=0x5555562f8430, font_object=0x5555569e1a45, fontset=-1) at xterm.c:26517
 > #1  0x00005555555c4656 in gui_set_font (f=0x5555562f8430, arg=0x5555568fe364, oldval=0x55555622d224) at frame.c:4733
 > #2  0x00005555555c1ff9 in gui_set_frame_parameters_1 (f=f@entry=0x5555562f8430, alist=<optimized out>, alist@entry=0x7fffffffd6f3, default_parameter=default_parameter@entry=true) at frame.c:4325
 > #3  0x000055555567fea1 in set_font_frame_param (lface=0x5555562f6e45, frame=0x5555562f8435) at xfaces.c:3816
 > #4  Finternal_set_lisp_face_attribute (face=0x5940, attr=<optimized out>, value=<optimized out>, frame=<optimized out>) at xfaces.c:3629
 > #5  0x000055555567eb38 in Finternal_set_lisp_face_attribute (face=0x5940, attr=0xdb0, value=0x5555568fe544, frame=<optimized out>) at xfaces.c:3092
 > ...
 >
 > vs
 >
 > (gdb) backtrace
 > #0  x_new_font (f=0x5555562f8430, font_object=0x555556945b6d, fontset=-1) at xterm.c:26517
 > #1  0x00005555555c4656 in gui_set_font (f=0x5555562f8430, arg=0x5555563e1e74, oldval=0x5555568fe364) at frame.c:4733
 > #2  0x00005555555c1ff9 in gui_set_frame_parameters_1 (f=f@entry=0x5555562f8430, alist=<optimized out>, alist@entry=0x7fffffffd6f3, default_parameter=default_parameter@entry=true) at frame.c:4325
 > #3  0x000055555567fea1 in set_font_frame_param (lface=0x5555562f6e45, frame=0x5555562f8435) at xfaces.c:3816
 > #4  Finternal_set_lisp_face_attribute (face=0x5940, attr=<optimized out>, value=<optimized out>, frame=<optimized out>) at xfaces.c:3629
 > #5  0x000055555567eb38 in Finternal_set_lisp_face_attribute (face=0x5940, attr=0x1020, value=0x1ba, frame=<optimized out>) at xfaces.c:3092
 > ...
 >
 > What seems to be different between the two are the font_object argument to x_new_font and the arguments to Finternal_set_lisp_face_attribute at the end of the backtrace.
 >
 > It seems like they are called twice because my original example sets two attributes: :height and :family.

So whenever we do 'set-face-attribute' to set both :height and :family,
we do the frame resizing twice, once for the family which apparently
assigns a new character size and once for the height.  This is bad: Why
ask the WM twice to set the frame size in one and the same call?  When
'frame-inhibit-implied-resize' is nil, these calls should be collapsed
into one and setting the size hint values should be always delayed.

 >>  > Should we try to circle back to finding the difference between
 >>  > "InconsolataLGC" and "Inconsolata LGC"? The latter doesn't exhibit
 >>  > most of the problematic behaviors we have been discussing here.
 >>
 >> The first thing to try would be obvious: Does the latter trigger the
 >> "two x_new_font entries in *foo* in a row behavior"?
 >
 > When called for the first time -- yes:
 >
 > x_new_font old char size 18x36 new char size 21x45 text chars 80x36 old text pixels 1440x1296 new text pixels 1680x1620
 > xg_wm_set_size_hint scale 2 char width 21 toolbar 0 vscroll 32 fringes 16 borders 0 text width 840 base width 34 width inc 10
 >      char height 45 menubar 50 toolbar 82 hscroll 0 borders 0 text height 810 base height 106 height inc 22
 > xg_frame_set_char_size old native pixels 1488x1296 new native pixels 1728x1620 outer pixels 864x876 outer rest 0x0
 >      base_size 34x106 size increments 10x22 WM hint 83x35
 > xg_frame_resized old native pixels 1488x1296 new native pixels 1728x1620
 > adjust_frame_size old native pixels 1488x1296 new native pixels 1728x1620 old text pixels 1440x1296 new text pixels 1680x1620 old text chars 80x36 new text chars 80x36
 >      base_size 34x106 size increments 10x22 WM hint 83x35
 >
 > x_new_font old char size 21x45 new char size 17x37 text chars 80x36 old text pixels 1680x1620 new text pixels 1360x1332
 > xg_wm_set_size_hint scale 2 char width 17 toolbar 0 vscroll 32 fringes 16 borders 0 text width 680 base width 32 width inc 8
 >      char height 37 menubar 50 toolbar 82 hscroll 0 borders 0 text height 666 base height 84 height inc 18
 > xg_frame_set_char_size old native pixels 1728x1620 new native pixels 1408x1332 outer pixels 704x732 outer rest 0x0
 >      base_size 32x84 size increments 8x18 WM hint 84x36
 > xg_frame_resized old native pixels 1728x1620 new native pixels 1408x1332
 > adjust_frame_size old native pixels 1728x1620 new native pixels 1408x1332 old text pixels 1680x1620 new text pixels 1360x1332 old text chars 80x36 new text chars 80x36
 >      base_size 32x84 size increments 8x18 WM hint 84x36
 >
 > When called the second time -- no:
 >
 > x_new_font old char size 17x37 new char size 17x37 text chars 80x36 old text pixels 1360x1332 new text pixels 1360x1332
 >
 > When called the third time and further -- no entries are added to *foo* at all.

OK.  But what _is_ the difference between the "InconsolataLGC" and
"Inconsolata LGC" calls here?  IIUC the "called for the first time"
behavior for "InconsolataLGC" is that the second x_new_font call does
not happen.  Is that right?  Please post the respective section of *foo*
for that first call so we can compare how it differs from the
"Inconsolata LGC" one.

To elaborate: The trace you show above resizes the frame twice,
apparently once for the :height and once for the :family change.  So we
should find out why the call for "InconsolataLGC" does not try to resize
the frame twice.  It should be something like not finding a suitable
font with "InconsolataLGC" or at least one that does not ask for
changing the height

BTW - do we call x_new_font for the :height first here (which would be
bad IMO)?

 >>  > Visually, the resulting text seems identical between these two
 >>  > fonts. Maybe the former font name is somehow "autocorrected" into the
 >>  > latter? And that triggers some kind of callback internally that can
 >>  > additionally resize the frame?
 >>
 >> Maybe fontset_from_font does such a thing.  We'd have to find out first
 >> whether the values x_new_font finds for font->average_width and
 >> font_ascent + font_descent differ for the two Inconsolatas.
 >
 > Anything I can evaluate to find that out?

We had it in *foo* but I removed it because it didn't show anything
unexpected.  Putting a breakpoint after the line

   get_font_ascent_descent (font, &font_ascent, &font_descent);

in xterm.c should do (it's probably the second hit).  Then print the
values of font->average_width, font_ascent and font_descent but make
sure to do it for both - "InconsolataLGC" and "Inconsolata LGC" - so we
can compare them.

Thanks, martin