Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with transient-posframe

From: Gerd Möllmann <[email-masked]>
Date: Wed, 14 May 2025 16:14:22 +0200

martin rudalics <[email-masked]> writes:

>> I see that the function is apparently called twice?
>
> Can you try to find out why?
>
>> And the output is
>>
>> 1: height 199
>> 2: height 199
>> height 199 text-minus-body-height 0
>> 1: height 199
>> 2: height 216
>> remainder 0 text-minus-body-height 0 char-height 18
>> height 216 text-minus-body-height 0
>>
>> Maybe the second '2:...' is what increases the frame size?
>
> I think so.  216 is the smallest multiple of 18 at least as large as
> 199.  That's what you will get anyway and should have happened also
> before my commit.  In a sense your were even lucky because if remainder
> were non-zero, it might have added another 17.  I probably should
> collapse these so at most 17 are added.
>
> But anyone who uses 'fit-frame-to-buffer' should have set
> 'frame-resize-pixelwise' to t.

I can't make much sense of it, ATM, but here's what I see. M-x
my-grab-bag is a transient.

First call. At this point, the transient is not yet visible on the
display.

  fit-frame-to-buffer-1(#<frame window.el 0x10b830000> 55 1 120 83 nil nil nil)
  posframe--fit-frame-to-buffer(#<frame window.el 0x10b830000> 55 1 120 83 nil)
  posframe--set-frame-size((:posframe #<frame window.el 0x10b830000> :width nil :height nil :max-width 120 :max-height 55 :min-width 83 :min-height 1))
  posframe-show(#<buffer  *transient*> :font nil :position 432383 :poshandler posframe-poshandler-frame-center :background-color "gray15" :foreground-color "white" :min-width 83 :internal-border-width 1 :internal-border-color "gray50" :override-parameters nil)
  transient-posframe--show-buffer(#<buffer  *transient*> nil)
  display-buffer(#<buffer  *transient*> (transient-posframe--show-buffer))
  transient--show()
  transient--redisplay()
  #f(compiled-function () #<bytecode -0x1b4f9e178d9e629f>)()
  transient--env-apply(#f(compiled-function () #<bytecode -0x1b4f9e178d9e629f>) #<transient-prefix 2b8339>)
  transient-setup(my-grab-bag)
  my-grab-bag()

Second call. The child frame is visible already.

  fit-frame-to-buffer-1(#<frame  0x10b830000> nil nil nil 83 nil t t)
  fit-frame-to-buffer(#<frame  0x10b830000> nil nil nil 83)
  transient--fit-window-to-buffer(#<window 14 on  *transient*>)
  transient--show()
  transient--redisplay()
  #f(compiled-function () #<bytecode -0x1b4f9e178d9e629f>)()
  transient--env-apply(#f(compiled-function () #<bytecode -0x1b4f9e178d9e629f>) #<transient-prefix 2b8339>)
  transient-setup(my-grab-bag)
  my-grab-bag()

Naively, I would assume that that all happens in the same
transient--redisplay -> transient--show, but I'm not sure of course.
The fit-frame-to-buffer in the second case is from here:

(defun transient--fit-window-to-buffer (window)
  (set-window-parameter window 'window-preserved-size nil)
  (let ((fit-window-to-buffer-horizontally t)
        (window-resize-pixelwise t)
        (window-size-fixed nil))
    (cond ((not (window-parent window))
           (fit-frame-to-buffer (window-frame window) nil nil nil
                                transient-minimal-frame-width))
          ((eq (car (window-parameter window 'quit-restore)) 'other)
           ;; Grow but never shrink window that previously displayed
           ;; another buffer and is going to display that again.
           (fit-window-to-buffer window nil (window-height window)))
          ((fit-window-to-buffer window nil 1))))
  (set-window-parameter window 'window-preserved-size
                        (list (window-buffer window)
                              (window-body-width window t)
                              (window-body-height window t))))

Should that have bound frame-resize-pixelwise? And if so why? I think I
understand more or less what the doc string of that variable says, but
the transient doesn't have anything I recognize that would make
pixel-wise resizing necessary. Or is some internal border or something?
Sorry, I'm in unknown territory here.