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: Dmitry Gutov <[email-masked]>
Date: Fri, 17 Feb 2023 04:05:58 +0200

Hi Martin,

It becomes ever more difficult to remember the context. E.g. which 
operations I should do with each build before looking up this or that value.

On 13/02/2023 12:09, martin rudalics wrote:
>  >>  > 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".

It seems like it would be better to just attach the foo logs for both. 
See foo-gtk3.txt and foo-lucid.txt attached.

These logs are of 'emacs -Q' followed by evaluating

   (set-face-attribute 'default nil :height 110 :family "InconsolataLGC")

>  >>  > 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.

Indeed. Not sure if it's supposed to.

The scrollbar itself is not very functional: it shows the scroll 
progress of the buffer, but to scroll back using the mouse clicks seems 
impossible (all scrolling proceeds in one direction).

>  > 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.

Makes sense. Though it's hard for me to tell at which step the variable 
should be appled.

>  >>  > 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.

First call for "InconsolataLGC":

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

The second and all subsequent ones look like this:

x_new_font old char size 17x37 new char size 17x37 text chars 80x36 old 
text pixels 1360x1332 new text pixels 1360x1332

x_new_font old char size 17x37 new char size 17x37 text chars 80x36 old 
text pixels 1360x1332 new text pixels 1360x1332

(This is while keeping the frame in its default size; no resizing with 
the mouse.)

> 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 looks like both trigger two x_new_fonts calls the first time. And 
maybe resize the frame twice, which could be hard to register with the 
human eye. But then one continues to do that (under certain conditions), 
and another stops.

> It should be something like not finding a suitable
> font with "InconsolataLGC" or at least one that does not ask for
> changing the height

That's what I was thinking: "InconsolataLGC" falls back to "Inconsolata 
LGC", but that's not registered in some internal data structure, so 
whenever a new set-face-attribute call arrives, the comparison fails, 
and the search is repeated.

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

That seems difficult to answer with gdb: too many 
internal-set-lisp-face-attribute calls during Emacs's startup.

But set-face-attribute's definition (and stepping through it with edebug 
for good measure) shows that :family is processed first.

I think this was also brought up in a recent bug discussion with 
Gregory: :family and :foundary and processed before the other 
attributes. But he recommended people used :font instead, for other reasons.

>  >>  > 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.

InconsolataLGC:

first hit:

(gdb) p font->average_width
$1 = 21
(gdb) p font_ascent
$2 = 37
(gdb) p font_descent
$3 = 8

second hit:

(gdb) p font->average_width
$4 = 17
(gdb) p font_ascent
$5 = 31
(gdb) p font_descent
$6 = 6

Inconsolata LGC:

Exactly the same.