Subject: bug#59547: 28.2; The bottom border is not displayed when setting the pixel height of a child frame smaller than 1 line

From: Yuwei Tian <[email-masked]>
Date: Mon, 28 Nov 2022 22:01:57 +0800

The problem reproduction code I gave is indeed problematic, and it is
indeed wrong to adjust 'window-safe-min-height' to 0.

The use case is to create a child frame with a height smaller than the
default line height, because the character size in the child frame is
set smaller than the default. How can this be achieved? Thanks.

On Mon, Nov 28, 2022 at 6:27 PM martin rudalics <[email-masked]> wrote:
>
>  > Start Emacs from 'Emacs -Q' and make a child frame with the following
>  > code:
>  >
>  > (let ((window-min-height 1)
>  >        (window-min-width 1))
>
> The last line is problematic since 'window-safe-min-width' being 2
> will override it.
>
>  >    (fit-frame-to-buffer my-child-frame)
>  >    (let ((window-min-height 0)
>  > (window-safe-min-height 0))
>  >      (set-frame-size my-child-frame
>  >      (frame-pixel-width my-child-frame)
>  >      (floor (* 0.5 (frame-pixel-height my-child-frame)))
>  >      t)))
>
> This is overly complicated.
>
>    (let ((window-min-height 0)
>         (window-safe-min-height 0))
>      (set-frame-size my-child-frame 50 8 t)))
>
> suffices to show the problem here.  In either case, you do two things
> which most people would classify as pilot errors.
>
> - You bind 'window-safe-min-height' which is defined as a constant
>    variable and according to the doc-string of 'defconst' "neither
>    programs nor users should ever change the value".
>
> - You temporarily bind 'window-min-height' around the 'set-frame-size'
>    call which means that it may not affect future resize operations on
>    'my-child-frame' or its windows.  In particular, it may not affect the
>    frame size adjustment triggered by 'set-frame-size' itself if that
>    happens asynchronously (not within the scope of 'set-frame-size').
>
>  > The bottom border of the child frame is not displayed. Try to resize the
>  > child frame again:
>  >
>  > (let ((window-min-height 0)
>  >        (window-safe-min-height 0))
>  >    (set-frame-size my-child-frame 50 8 t))
>  >
>  > And select other window, then the bottom border of the child frame appears.
>
> Here clicking into the child frame with the mouse suffices to make the
> bottom border appear.
>
>  > This behavior seems to be platform dependent, but it is indeed
>  > problematic. It also seems to have problems on Emacs 28, Linux/X11.
>
> The immediate cause of the problem are these two lines in window.c's
> resize_frame_windows code:
>
>    new_pixel_size = max (horflag ? size : size - mini_height, unit);
>    new_size = new_pixel_size / unit;
>
> where unit is defined as
>
>    int unit = horflag ? FRAME_COLUMN_WIDTH (f) : FRAME_LINE_HEIGHT (f);
>
> As a consequence, 'compute_line_metrics' in xdisp.c will calculate
>
>        max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
>
>        if (row->y + row->height > max_y)
>         row->visible_height -= row->y + row->height - max_y;
>
> from the value of 'unit' above, the text is not clipped and whether you
> see the lower border or the lower part of the buffer text reduces to the
> question of who succeeds in drawing later into that area - the code
> displaying the buffer text or the one filling the border rectangle.
>
> If you replace these two lines with say
>
>    new_pixel_size = max (horflag ? size : size - mini_height, 1);
>    new_size = max (new_pixel_size / unit, unit);
>
> you should get the bottom border immediately.  Whether applying such a
> "fix" is safe, is a question I cannot answer though.  Here I'm living
> happily with fixes for this and many related problems but have no hope
> that they will ever see the light of master.
>
> martin