GNU bug report logs - #78418
31.0.50; Change in fit-frame-to-buffer doesn't work with transient-posframe

Previous Next

Package: emacs;

Reported by: Gerd Möllmann <gerd.moellmann <at> gmail.com>

Date: Wed, 14 May 2025 07:22:01 UTC

Severity: normal

Found in version 31.0.50

To reply to this bug, email your comments to 78418 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 07:22:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Gerd Möllmann <gerd.moellmann <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Wed, 14 May 2025 07:22:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Cc: Martin Rudalics <rudalics <at> gmx.at>, yhaoxie <at> gmail.com
Subject: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 09:21:05 +0200
[Message part 1 (text/plain, inline)]
In GNU Emacs 31.0.50 (build 1, aarch64-apple-darwin24.5.0, NS
 appkit-2575.60 Version 15.5 (Build 24F74)) of 2025-05-13 built on pro2

The transient-posframe display changed which I bisected to

  6017c6a986fd958732facb1bb6ea2c040981b023 is the first bad commit
  commit 6017c6a986fd958732facb1bb6ea2c040981b023
  Author: Martin Rudalics <rudalics <at> gmx.at>
  Date:   Mon Dec 23 10:59:11 2024 +0100
      Make 'fit-frame-to-buffer' work around size hints (Bug#74866)

      * lisp/window.el (fit-frame-to-buffer-1): When
      'frame-resize-pixelwise' is nil, round up requested sizes to avoid
      that lines get wrapped (Bug#74866).
      * doc/lispref/windows.texi (Resizing Windows): Mention that with
      size hints one may have to set 'frame-resize-pixelwise' to make
      'fit-frame-to-buffer' fit the buffer exactly.
   doc/lispref/windows.texi |  4 +++-
   lisp/window.el           | 20 ++++++++++++++++++++
   2 files changed, 23 insertions(+), 1 deletion(-)

After that change, an additional line is displayed at the bottom of the
child frame that transient-posframe uses to display a transient.

Screen shot from the NS GUI on macOS:

[Screenshot 2025-05-14 at 09.05.30.png (image/png, attachment)]
[Message part 3 (text/plain, inline)]
On ttys, the pixel-wide line above the additional line is not present,
of course.

Added Martin and the author of transient-posframe in CC.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 08:15:03 GMT) Full text and rfc822 format available.

Message #8 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>,
 bug-gnu-emacs <at> gnu.org
Cc: yhaoxie <at> gmail.com
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 10:14:43 +0200
> Added Martin and the author of transient-posframe in CC.

In this piece of code

	(setq text-minus-body-height
	      (+ text-minus-body-height
		 (- char-height
		    (% text-minus-body-height char-height)))))

what are the values of 'text-minus-body-height' and 'char-height' when
the problem happens?

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 08:28:05 GMT) Full text and rfc822 format available.

Message #11 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 10:26:50 +0200
martin rudalics <rudalics <at> gmx.at> writes:

>> Added Martin and the author of transient-posframe in CC.
>
> In this piece of code
>
> 	(setq text-minus-body-height
> 	      (+ text-minus-body-height
> 		 (- char-height
> 		    (% text-minus-body-height char-height)))))
>
> what are the values of 'text-minus-body-height' and 'char-height' when
> the problem happens?
>
> martin

text-minus-body-height 0, char-height 1

with

modified   lisp/window.el
@@ -10157,6 +10157,8 @@ fit-frame-to-buffer-1
 	      (+ text-minus-body-width
 		 (- char-width
 		    (% text-minus-body-width char-width))))
+        (message "text-minus-body-height %S, char-height %S"
+                 text-minus-body-height char-height)
 	(setq text-minus-body-height
 	      (+ text-minus-body-height
 		 (- char-height

in an Emacs on tty.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 09:09:03 GMT) Full text and rfc822 format available.

Message #14 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 11:08:09 +0200
>> what are the values of 'text-minus-body-height' and 'char-height' when
>> the problem happens?
>>
>> martin
>
> text-minus-body-height 0, char-height 1

Thanks.  Silly thinko then and the below should fix it.

martin

diff --git a/lisp/window.el b/lisp/window.el
index e0e626e9500..e372ef8b9bb 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -10153,14 +10153,14 @@ fit-frame-to-buffer-1
 	;; this may cause lines getting wrapped.  To avoid that, round
 	;; sizes up here which will, however, leave a blank space at the
 	;; end of the longest line(s).
-	(setq text-minus-body-width
-	      (+ text-minus-body-width
-		 (- char-width
-		    (% text-minus-body-width char-width))))
-	(setq text-minus-body-height
-	      (+ text-minus-body-height
-		 (- char-height
-		    (% text-minus-body-height char-height)))))
+	(let ((remainder (% text-minus-body-width char-width)))
+	  (unless (zerop remainder)
+	    (setq text-minus-body-width
+		  (+ text-minus-body-width (- char-width remainder)))))
+	(let ((remainder (% text-minus-body-height char-height)))
+	  (unless (zerop remainder)
+	    (setq text-minus-body-height
+		  (+ text-minus-body-height(- char-height remainder))))))
       (setq text-width
             (if width
                 (+ width text-minus-body-width)




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 09:49:02 GMT) Full text and rfc822 format available.

Message #17 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 11:48:02 +0200
martin rudalics <rudalics <at> gmx.at> writes:

>  >> what are the values of 'text-minus-body-height' and 'char-height' when
>  >> the problem happens?
>  >>
>  >> martin
>  >
>  > text-minus-body-height 0, char-height 1
>
> Thanks.  Silly thinko then and the below should fix it.
>
> martin
>
> diff --git a/lisp/window.el b/lisp/window.el
> index e0e626e9500..e372ef8b9bb 100644
> --- a/lisp/window.el
> +++ b/lisp/window.el
> @@ -10153,14 +10153,14 @@ fit-frame-to-buffer-1
>   	;; this may cause lines getting wrapped.  To avoid that, round
>   	;; sizes up here which will, however, leave a blank space at the
>   	;; end of the longest line(s).
> -	(setq text-minus-body-width
> -	      (+ text-minus-body-width
> -		 (- char-width
> -		    (% text-minus-body-width char-width))))
> -	(setq text-minus-body-height
> -	      (+ text-minus-body-height
> -		 (- char-height
> -		    (% text-minus-body-height char-height)))))
> +	(let ((remainder (% text-minus-body-width char-width)))
> +	  (unless (zerop remainder)
> +	    (setq text-minus-body-width
> +		  (+ text-minus-body-width (- char-width remainder)))))
> +	(let ((remainder (% text-minus-body-height char-height)))
> +	  (unless (zerop remainder)
> +	    (setq text-minus-body-height
> +		  (+ text-minus-body-height(- char-height remainder))))))
>         (setq text-width
>               (if width
>                   (+ width text-minus-body-width)

Thanks, that fixes the tty case, but on the GUI it still looks like in
the screen shot I sent. With

modified   lisp/window.el
@@ -10158,6 +10158,8 @@ fit-frame-to-buffer-1
 	    (setq text-minus-body-width
 		  (+ text-minus-body-width (- char-width remainder)))))
 	(let ((remainder (% text-minus-body-height char-height)))
+          (message "remainder %S text-minus-body-height %S char-height %S"
+                   remainder text-minus-body-height char-height)
 	  (unless (zerop remainder)
 	    (setq text-minus-body-height
 		  (+ text-minus-body-height(- char-height remainder))))))

it says

remainder 0 text-minus-body-height 0 char-height 18




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 12:00:08 GMT) Full text and rfc822 format available.

Message #20 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 13:59:05 +0200
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:

> martin rudalics <rudalics <at> gmx.at> writes:
>
>>  >> what are the values of 'text-minus-body-height' and 'char-height' when
>>  >> the problem happens?
>>  >>
>>  >> martin
>>  >
>>  > text-minus-body-height 0, char-height 1
>>
>> Thanks.  Silly thinko then and the below should fix it.
>>
>> martin
>>
>> diff --git a/lisp/window.el b/lisp/window.el
>> index e0e626e9500..e372ef8b9bb 100644
>> --- a/lisp/window.el
>> +++ b/lisp/window.el
>> @@ -10153,14 +10153,14 @@ fit-frame-to-buffer-1
>>   	;; this may cause lines getting wrapped.  To avoid that, round
>>   	;; sizes up here which will, however, leave a blank space at the
>>   	;; end of the longest line(s).
>> -	(setq text-minus-body-width
>> -	      (+ text-minus-body-width
>> -		 (- char-width
>> -		    (% text-minus-body-width char-width))))
>> -	(setq text-minus-body-height
>> -	      (+ text-minus-body-height
>> -		 (- char-height
>> -		    (% text-minus-body-height char-height)))))
>> +	(let ((remainder (% text-minus-body-width char-width)))
>> +	  (unless (zerop remainder)
>> +	    (setq text-minus-body-width
>> +		  (+ text-minus-body-width (- char-width remainder)))))
>> +	(let ((remainder (% text-minus-body-height char-height)))
>> +	  (unless (zerop remainder)
>> +	    (setq text-minus-body-height
>> +		  (+ text-minus-body-height(- char-height remainder))))))
>>         (setq text-width
>>               (if width
>>                   (+ width text-minus-body-width)
>
> Thanks, that fixes the tty case, but on the GUI it still looks like in
> the screen shot I sent. With
>
> modified   lisp/window.el
> @@ -10158,6 +10158,8 @@ fit-frame-to-buffer-1
>  	    (setq text-minus-body-width
>  		  (+ text-minus-body-width (- char-width remainder)))))
>  	(let ((remainder (% text-minus-body-height char-height)))
> +          (message "remainder %S text-minus-body-height %S char-height %S"
> +                   remainder text-minus-body-height char-height)
>  	  (unless (zerop remainder)
>  	    (setq text-minus-body-height
>  		  (+ text-minus-body-height(- char-height remainder))))))
>
> it says
>
> remainder 0 text-minus-body-height 0 char-height 18

When I invoke a transient in the GUI, and with this diff

1 file changed, 6 insertions(+)
lisp/window.el | 6 ++++++

modified   lisp/window.el
@@ -10126,9 +10126,11 @@ fit-frame-to-buffer-1
             (setq left left-margin)))))
       ;; Fit height to constraints.
       (when height
+        (message "1: height %S" height)
         (unless frame-resize-pixelwise
           (setq height (* (/ (+ height char-height -1) char-height)
                           char-height)))
+        (message "2: height %S" height)
         ;; The new outer height.
         (setq outer-height (+ height outer-minus-body-height))
         ;; Preserve margins.
@@ -10158,6 +10160,8 @@ fit-frame-to-buffer-1
 	    (setq text-minus-body-width
 		  (+ text-minus-body-width (- char-width remainder)))))
 	(let ((remainder (% text-minus-body-height char-height)))
+          (message "remainder %S text-minus-body-height %S char-height %S"
+                   remainder text-minus-body-height char-height)
 	  (unless (zerop remainder)
 	    (setq text-minus-body-height
 		  (+ text-minus-body-height(- char-height remainder))))))
@@ -10165,6 +10169,8 @@ fit-frame-to-buffer-1
             (if width
                 (+ width text-minus-body-width)
               (frame-text-width frame)))
+      (message "height %S text-minus-body-height %S"
+               height text-minus-body-height)
       (setq text-height
             (if height
                 (+ height text-minus-body-height)

I see that the function is apparently called twice? 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?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 13:47:02 GMT) Full text and rfc822 format available.

Message #23 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 15:46:23 +0200
> When I invoke a transient in the GUI, and with this diff
>
> 1 file changed, 6 insertions(+)
> lisp/window.el | 6 ++++++
>
> modified   lisp/window.el
> @@ -10126,9 +10126,11 @@ fit-frame-to-buffer-1
>               (setq left left-margin)))))
>         ;; Fit height to constraints.
>         (when height
> +        (message "1: height %S" height)
>           (unless frame-resize-pixelwise
>             (setq height (* (/ (+ height char-height -1) char-height)
>                             char-height)))
> +        (message "2: height %S" height)
>           ;; The new outer height.
>           (setq outer-height (+ height outer-minus-body-height))
>           ;; Preserve margins.
> @@ -10158,6 +10160,8 @@ fit-frame-to-buffer-1
>   	    (setq text-minus-body-width
>   		  (+ text-minus-body-width (- char-width remainder)))))
>   	(let ((remainder (% text-minus-body-height char-height)))
> +          (message "remainder %S text-minus-body-height %S char-height %S"
> +                   remainder text-minus-body-height char-height)
>   	  (unless (zerop remainder)
>   	    (setq text-minus-body-height
>   		  (+ text-minus-body-height(- char-height remainder))))))
> @@ -10165,6 +10169,8 @@ fit-frame-to-buffer-1
>               (if width
>                   (+ width text-minus-body-width)
>                 (frame-text-width frame)))
> +      (message "height %S text-minus-body-height %S"
> +               height text-minus-body-height)
>         (setq text-height
>               (if height
>                   (+ height text-minus-body-height)
>
> 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.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 14:15:04 GMT) Full text and rfc822 format available.

Message #26 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 16:14:22 +0200
martin rudalics <rudalics <at> gmx.at> 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.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 14:25:02 GMT) Full text and rfc822 format available.

Message #29 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 16:24:28 +0200
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:

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

When I add a binding for frame-resize-pixelwise, things seem to work on
the GUI, BTW.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 15:12:03 GMT) Full text and rfc822 format available.

Message #32 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 17:11:08 +0200
>>> 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
[...]
> 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()

The mysterious thing is that in the first call 'fit-frame-to-buffer-1'
did _not_ round from 199 to 216.

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

And in the second call it did round.  But note that this call has many
arguments that differ from the first.

> The fit-frame-to-buffer in the second case is from here:

And that from the first case?

> (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?

It should _not_ since 'frame-resize-pixelwise' is a user variable.

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

If 'fit-frame-to-buffer' resizes pixelwise and 'frame-resize-pixelwise'
is globally nil, the WM may round down to character sizes which usually
means that text gets truncated.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 15:13:02 GMT) Full text and rfc822 format available.

Message #35 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 17:11:17 +0200
> When I add a binding for frame-resize-pixelwise, things seem to work on
> the GUI, BTW.

But why do you think that things don't work on the GUI?  You see 17
extra pixels needed to round the text size to the next multiple of 18.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 16:22:02 GMT) Full text and rfc822 format available.

Message #38 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org, Feng Shu <tumashu <at> 163.com>
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 18:20:14 +0200
martin rudalics <rudalics <at> gmx.at> writes:

>>>> 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
> [...]
>> 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()
>
> The mysterious thing is that in the first call 'fit-frame-to-buffer-1'
> did _not_ round from 199 to 216.
>
>> 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.
>
> And in the second call it did round.  But note that this call has many
> arguments that differ from the first.
>
>> The fit-frame-to-buffer in the second case is from here:
>
> And that from the first case?

That's

posframe.el:
  840 (defun posframe--fit-frame-to-buffer (posframe max-height min-height max-width min-width only)
  841   "POSFRAME version of function `fit-frame-to-buffer'.
  842 Arguments HEIGHT, MAX-HEIGHT, MIN-HEIGHT, WIDTH, MAX-WIDTH,
  843 MIN-WIDTH and ONLY are similar function `fit-frame-to-buffer''s."
  844   ;; This only has effect if the user set the latter var to `hide'.
  845   (let ((x-gtk-resize-child-frames posframe-gtk-resize-child-frames))
  846     ;; More info: Don't skip empty lines when fitting mini frame to buffer (Bug#44080)
  847     ;; http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=e0de9f3295b4c46cb7198ec0b9634809d7b7a36d
  848     (if (functionp 'fit-frame-to-buffer-1)
  849         (fit-frame-to-buffer-1
  850          posframe max-height min-height max-width min-width only nil nil)
  851       (fit-frame-to-buffer
  852        posframe max-height min-height max-width min-width only))))

And after some digging, I found several bindings for
frame-resize-pixel-wise, for example in posframe-show which is in the
backtrace.

posframe.el:
  419                               (window-tab-line-height)
  420                             0))
  421          (mouse-position (cdr (mouse-pixel-position)))
  422          (frame-resize-pixelwise t)
  423          posframe)

If I understand correctly what you write further down, this should not
be done, right? (Feng Shu <tumashu <at> 163.com> added to CC, the posframe
author).

Si I guess that explains that difference.

>
>> (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?
>
> It should _not_ since 'frame-resize-pixelwise' is a user variable.
>
>> 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.
>
> If 'fit-frame-to-buffer' resizes pixelwise and 'frame-resize-pixelwise'
> is globally nil, the WM may round down to character sizes which usually
> means that text gets truncated.

If you express it that way, I almost understand what it does :-). So, if
my WM is not ever rounding down, I should set it to t? Might be a good
default for macOS...





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 16:27:02 GMT) Full text and rfc822 format available.

Message #41 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 18:25:41 +0200
[Message part 1 (text/plain, inline)]
martin rudalics <rudalics <at> gmx.at> writes:

>> When I add a binding for frame-resize-pixelwise, things seem to work on
>> the GUI, BTW.
>
> But why do you think that things don't work on the GUI?  You see 17
> extra pixels needed to round the text size to the next multiple of 18.

Here's what I see.

[Screenshot 2025-05-14 at 18.21.49.png (image/png, inline)]
[Message part 3 (text/plain, inline)]
This time, for whatever reason, with 2 extra lines plus a 1-pixel
separator line wherever that comes from. Both the extra lines and the
separator were not there before.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Wed, 14 May 2025 17:45:01 GMT) Full text and rfc822 format available.

Message #44 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org, Feng Shu <tumashu <at> 163.com>
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Wed, 14 May 2025 19:44:29 +0200
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:

>> If 'fit-frame-to-buffer' resizes pixelwise and 'frame-resize-pixelwise'
>> is globally nil, the WM may round down to character sizes which usually
>> means that text gets truncated.
>
> If you express it that way, I almost understand what it does :-). So, if
> my WM is not ever rounding down, I should set it to t? Might be a good
> default for macOS...

And changing the default to t seems to work well with GUI and TUI
version.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Thu, 15 May 2025 08:15:01 GMT) Full text and rfc822 format available.

Message #47 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Thu, 15 May 2025 10:13:50 +0200
> 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.

I forgot: I can't collapse them because of the way we set WM size hints.
That's broken for practically all platforms and fixing it will hardly
happen ever.  Which means that with 'frame-resize-pixelwise' we

- first have to round the calculated text size to the next multiple of
  character sizes

- and then have to round the size of the decorations to the next
  multiple of character sizes.

We pass the rounded text size as base size, the character size as
increment and the sum of rounded text and rounded decorations size as
preferred size of the frame.  So with a default character height of 18
pixels you will get 34 extra pixels in the worst case and I see no
practical way to fix that.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Thu, 15 May 2025 08:15:02 GMT) Full text and rfc822 format available.

Message #50 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Thu, 15 May 2025 10:14:03 +0200
> This time, for whatever reason, with 2 extra lines plus a 1-pixel
> separator line wherever that comes from. Both the extra lines and the
> separator were not there before.

The separator must come from elsewhere.  The extra lines are probably
not entirely full - they should sum up to 34 pixels at most with your
settings.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Thu, 15 May 2025 08:16:02 GMT) Full text and rfc822 format available.

Message #53 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org, Feng Shu <tumashu <at> 163.com>
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Thu, 15 May 2025 10:14:42 +0200
[Message part 1 (text/plain, inline)]
>> And that from the first case?
>
> That's
>
> posframe.el:
>    840 (defun posframe--fit-frame-to-buffer (posframe max-height min-height max-width min-width only)
>    841   "POSFRAME version of function `fit-frame-to-buffer'.
>    842 Arguments HEIGHT, MAX-HEIGHT, MIN-HEIGHT, WIDTH, MAX-WIDTH,
>    843 MIN-WIDTH and ONLY are similar function `fit-frame-to-buffer''s."
>    844   ;; This only has effect if the user set the latter var to `hide'.
>    845   (let ((x-gtk-resize-child-frames posframe-gtk-resize-child-frames))
>    846     ;; More info: Don't skip empty lines when fitting mini frame to buffer (Bug#44080)
>    847     ;; http://git.savannah.gnu.org/cgit/emacs.git/commit/?id=e0de9f3295b4c46cb7198ec0b9634809d7b7a36d
>    848     (if (functionp 'fit-frame-to-buffer-1)
>    849         (fit-frame-to-buffer-1
>    850          posframe max-height min-height max-width min-width only nil nil)
>    851       (fit-frame-to-buffer
>    852        posframe max-height min-height max-width min-width only))))

This doesn't explain the 199 vs 216 dichotomy yet.

> And after some digging, I found several bindings for
> frame-resize-pixel-wise, for example in posframe-show which is in the
> backtrace.
>
> posframe.el:
>    419                               (window-tab-line-height)
>    420                             0))
>    421          (mouse-position (cdr (mouse-pixel-position)))
>    422          (frame-resize-pixelwise t)
>    423          posframe)
>
> If I understand correctly what you write further down, this should not
> be done, right? (Feng Shu <tumashu <at> 163.com> added to CC, the posframe
> author).

It might work if the frame is short-lived enough.  The problem with it
is that subsequent operations on that frame will immediately undo the
pixelwise effect unless they again bind 'frame-resize-pixelwise'.

> Si I guess that explains that difference.

You would have to always report the value of 'frame-resize-pixelwise'
too when you report the values calculated by 'fit-frame-to-buffer'.

> If you express it that way, I almost understand what it does :-).

Users should always set 'frame-resize-pixelwise' to t unless they rely
on two effects provided by window managers:

- When you drag a frame border with the mouse a pixelwise frame grows or
  shrinks by one pixel.  A non-pixelwise frame can grow or shrink by a
  line and/or column only.

- With some WMs when you drag a frame border with the mouse you get some
  feedback about the current size of the frame in some sort of a window
  on top of it.  See the attached resize.png with the (84x36) text in
  the center of the frame - that's how xfwm displays that information
  here.

Non-pixelwise frames behave like terminal windows - they cannot be
maximized orderly and do not play well with tiling WMs.  And since we
never fixed size hints to work orderly with decorations, frames cannot
be fit well to the sizes of their buffers.

> So, if
> my WM is not ever rounding down, I should set it to t? Might be a good
> default for macOS...

I would set it regardless of whether my WM rounds down or not.

martin
[resize.png (image/png, attachment)]

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Thu, 15 May 2025 08:47:03 GMT) Full text and rfc822 format available.

Message #56 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org, Feng Shu <tumashu <at> 163.com>
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Thu, 15 May 2025 10:45:59 +0200
martin rudalics <rudalics <at> gmx.at> writes:

>> So, if
>> my WM is not ever rounding down, I should set it to t? Might be a good
>> default for macOS...
>
> I would set it regardless of whether my WM rounds down or not.

Yeah, I've done that now in my init.el, and so far I haven't seen ill
effects. I guess some macOS users using posframe-transient might
eventually complain, but nwo that the role of frame-resize-pixelwise is
clearer... (What a maze, that frame stuff :-(). 




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Mon, 19 May 2025 07:54:02 GMT) Full text and rfc822 format available.

Message #59 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Mon, 19 May 2025 09:53:43 +0200
> Thanks, that fixes the tty case, but on the GUI it still looks like in
> the screen shot I sent.

I checked in this fix so the tty case should be OK now.  As for the GUI
case I'm not sure what to do.  Currently, our size hints are Potemkin
villages and I doubt this will ever change.  What would have to be done
at the very least is:

- Specify resize increments for frames separately so frames meant to be
  fit to their buffers (like those of posframe) could be always fit
  exactly without compromising the behavior for normal frames.  This is
  a non-invasive change but it will take some time until the designers
  of child frame based solutions will pick it up.

- Fix the base and minimum size calculations.  This is an invasive
  change since base and minimum sizes may change all the times and we
  have to inform the WM about each such change.

- Fix gravity.  Currently, all nonX platforms have to separately define
  ten gravity values which are completely useless.  All we pass to a WM
  is NorthWestGravity although other values would make sense for child
  frames.  Changing this is easy but we would have to provide emulations
  for WMs that do not heed size hints which is tedious.

- Fix the XNegative/Negative values.  This way we could leave it to the
  WM to exactly align frames to the right and bottom edges of a display
  or parent frame whenever frame sizes change (recall the examples we
  early tested for how to correctly align initial frames against these
  edges).  Again we would have to emulate that for WMs that ignore size
  hints.

Personally I have no hope that any of these will ever see the light of
the day.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Mon, 19 May 2025 08:24:02 GMT) Full text and rfc822 format available.

Message #62 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Mon, 19 May 2025 10:23:05 +0200
martin rudalics <rudalics <at> gmx.at> writes:

>> Thanks, that fixes the tty case, but on the GUI it still looks like in
>> the screen shot I sent.
>
> I checked in this fix so the tty case should be OK now.  

Thanks!

> As for the GUI case I'm not sure what to do. Currently, our size hints
> are Potemkin villages and I doubt this will ever change. What would
> have to be done at the very least is:
>
> - Specify resize increments for frames separately so frames meant to be
>   fit to their buffers (like those of posframe) could be always fit
>   exactly without compromising the behavior for normal frames.  This is
>   a non-invasive change but it will take some time until the designers
>   of child frame based solutions will pick it up.
>
> - Fix the base and minimum size calculations.  This is an invasive
>   change since base and minimum sizes may change all the times and we
>   have to inform the WM about each such change.
>
> - Fix gravity.  Currently, all nonX platforms have to separately define
>   ten gravity values which are completely useless.  All we pass to a WM
>   is NorthWestGravity although other values would make sense for child
>   frames.  Changing this is easy but we would have to provide emulations
>   for WMs that do not heed size hints which is tedious.
>
> - Fix the XNegative/Negative values.  This way we could leave it to the
>   WM to exactly align frames to the right and bottom edges of a display
>   or parent frame whenever frame sizes change (recall the examples we
>   early tested for how to correctly align initial frames against these
>   edges).  Again we would have to emulate that for WMs that ignore size
>   hints.
>
> Personally I have no hope that any of these will ever see the light of
> the day.

Maybe we should set the default of frame-resize-pixelwise to true? Or at
least on macOS? IIRC you recommended setting it to true unless the WM
does mess with the frame size. On macOS this seems to be the right
default.





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Mon, 19 May 2025 10:02:03 GMT) Full text and rfc822 format available.

Message #65 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Mon, 19 May 2025 12:01:48 +0200
> Maybe we should set the default of frame-resize-pixelwise to true? Or at
> least on macOS? IIRC you recommended setting it to true unless the WM
> does mess with the frame size.

As a rule WMs don't mess with frame sizes.  Today most WMs DTRT.
Setting it to t means that people who expect their frames to always
resize only by character increments will holler.

> On macOS this seems to be the right
> default.

When on macOS with 'frame-resize-pixelwise' nil you drag a frame border
with the mouse, does it resize by pixels or by character increments?

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Mon, 19 May 2025 10:46:01 GMT) Full text and rfc822 format available.

Message #68 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Mon, 19 May 2025 12:45:10 +0200
martin rudalics <rudalics <at> gmx.at> writes:

>> Maybe we should set the default of frame-resize-pixelwise to true? Or at
>> least on macOS? IIRC you recommended setting it to true unless the WM
>> does mess with the frame size.
>
> As a rule WMs don't mess with frame sizes.  Today most WMs DTRT.
> Setting it to t means that people who expect their frames to always
> resize only by character increments will holler.
>
>> On macOS this seems to be the right
>> default.
>
> When on macOS with 'frame-resize-pixelwise' nil you drag a frame border
> with the mouse, does it resize by pixels or by character increments?

I think it resizes to character bounds with frame-resize-pixelwise nil,
and to pixels with it being t.

For transient-posframe child frames, when f-r-p is nil. things go wrong
because Posframe binds frame-resize-pixelwise to t, and transient uses
the default nil when fit-frame-to-buffer is called. That's what I showed
in the screen shot.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Mon, 19 May 2025 13:47:02 GMT) Full text and rfc822 format available.

Message #71 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Mon, 19 May 2025 15:45:55 +0200
>> When on macOS with 'frame-resize-pixelwise' nil you drag a frame border
>> with the mouse, does it resize by pixels or by character increments?
>
> I think it resizes to character bounds with frame-resize-pixelwise nil,
> and to pixels with it being t.

But did you try?  I see PResizeInc defined in nsgui.h but I nowhere see
it used.  Same goes for Wayland builds.  AFAICT size increments are only
recognized by X11.  Everywhere else they are a pure nuisance.

> For transient-posframe child frames, when f-r-p is nil. things go wrong
> because Posframe binds frame-resize-pixelwise to t, and transient uses
> the default nil when fit-frame-to-buffer is called. That's what I showed
> in the screen shot.

That's a different issue.  If 'frame-resize-pixelwise' is nil,
'fit-frame-to-buffer-1' does all that silly rounding which blows frames
up in your case.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Mon, 19 May 2025 14:06:01 GMT) Full text and rfc822 format available.

Message #74 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Mon, 19 May 2025 16:04:36 +0200
[Message part 1 (text/plain, inline)]
martin rudalics <rudalics <at> gmx.at> writes:

>>> When on macOS with 'frame-resize-pixelwise' nil you drag a frame border
>>> with the mouse, does it resize by pixels or by character increments?
>>
>> I think it resizes to character bounds with frame-resize-pixelwise nil,
>> and to pixels with it being t.
>
> But did you try?  

Sure. With frame-resize-pixelwise t, I can drag the right side of the
frame so that I get this:

[Screenshot 2025-05-19 at 15.52.05.png (image/png, inline)]
[Message part 3 (text/plain, inline)]
Note that I can make it end in the middle of the 'm' in the header-line.
With frame-resize-pixel-wise nil I can't get that. It "snaps" to character
boundaries like so

[Screenshot 2025-05-19 at 15.53.24.png (image/png, inline)]
[Message part 5 (text/plain, inline)]
> I see PResizeInc defined in nsgui.h but I nowhere see it used. Same
> goes for Wayland builds. AFAICT size increments are only recognized by
> X11. Everywhere else they are a pure nuisance.

Don't know what that means, sorry. And I don't know what is causing
this different behavior.

>> For transient-posframe child frames, when f-r-p is nil. things go wrong
>> because Posframe binds frame-resize-pixelwise to t, and transient uses
>> the default nil when fit-frame-to-buffer is called. That's what I showed
>> in the screen shot.
>
> That's a different issue.  If 'frame-resize-pixelwise' is nil,
> 'fit-frame-to-buffer-1' does all that silly rounding which blows frames
> up in your case.

It's the only reason I ask if we should change the default value. Or
Posframe shouldn't bind frame-resize-pixelwise, or Transient should not
call fit-buffer-to-frame, or whatever. As it stands, it will lead to bug
reports. Not that it matters much, of course.

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Mon, 19 May 2025 14:09:03 GMT) Full text and rfc822 format available.

Message #77 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Mon, 19 May 2025 16:08:13 +0200
Gerd Möllmann <gerd.moellmann <at> gmail.com> writes:

> martin rudalics <rudalics <at> gmx.at> writes:
>
>>>> When on macOS with 'frame-resize-pixelwise' nil you drag a frame border
>>>> with the mouse, does it resize by pixels or by character increments?
>>>
>>> I think it resizes to character bounds with frame-resize-pixelwise nil,
>>> and to pixels with it being t.
>>
>> But did you try?  
>
> Sure. With frame-resize-pixelwise t, I can drag the right side of the
> frame so that I get this:
>
> x
>
>
> Note that I can make it end in the middle of the 'm' in the header-line.
> With frame-resize-pixel-wise nil I can't get that. It "snaps" to character
> boundaries like so
>
> x
>
>
>> I see PResizeInc defined in nsgui.h but I nowhere see it used. Same
>> goes for Wayland builds. AFAICT size increments are only recognized by
>> X11. Everywhere else they are a pure nuisance.
>
> Don't know what that means, sorry. And I don't know what is causing
> this different behavior.

Could be this, maybe

nsterm.m:
 7967   /* Restrict the new size to the text grid.
 7968 
 7969      Don't restrict the width if the user only adjusted the height, and
 7970      vice versa.  (Without this, the frame would shrink, and move
 7971      slightly, if the window was resized by dragging one of its
 7972      borders.)  */
 7973   if (!frame_resize_pixelwise)
 7974     {
 7975       NSRect r = [[self window] frame];
 7976 
 7977       if (r.size.width != frameSize.width)
 7978         {
 7979           frameSize.width =
 7980             FRAME_TEXT_COLS_TO_PIXEL_WIDTH  (*emacsframe, cols);
 7981         }
 7982 
 7983       if (r.size.height != frameSize.height)
 7984         {
 7985           frameSize.height =
 7986             FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (*emacsframe, rows) + extra;
 7987         }
 7988     }

in - (NSSize)windowWillResize:




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Mon, 19 May 2025 14:39:01 GMT) Full text and rfc822 format available.

Message #80 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Mon, 19 May 2025 16:38:12 +0200
> Could be this, maybe
>
> nsterm.m:
>   7967   /* Restrict the new size to the text grid.
>   7968
>   7969      Don't restrict the width if the user only adjusted the height, and
>   7970      vice versa.  (Without this, the frame would shrink, and move
>   7971      slightly, if the window was resized by dragging one of its
>   7972      borders.)  */
>   7973   if (!frame_resize_pixelwise)
>   7974     {
>   7975       NSRect r = [[self window] frame];
>   7976
>   7977       if (r.size.width != frameSize.width)
>   7978         {
>   7979           frameSize.width =
>   7980             FRAME_TEXT_COLS_TO_PIXEL_WIDTH  (*emacsframe, cols);
>   7981         }
>   7982
>   7983       if (r.size.height != frameSize.height)
>   7984         {
>   7985           frameSize.height =
>   7986             FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (*emacsframe, rows) + extra;
>   7987         }
>   7988     }
>
> in - (NSSize)windowWillResize:

Looks like it.  Does the edge "snap back" when you release the mouse
button in the middle of the "m"?  And the Haiku build does something
similar apparently.

martin




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Mon, 19 May 2025 14:46:02 GMT) Full text and rfc822 format available.

Message #83 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Gerd Möllmann <gerd.moellmann <at> gmail.com>
To: martin rudalics <rudalics <at> gmx.at>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Mon, 19 May 2025 16:45:16 +0200
martin rudalics <rudalics <at> gmx.at> writes:

>> in - (NSSize)windowWillResize:
>
> Looks like it.  Does the edge "snap back" when you release the mouse
> button in the middle of the "m"?  And the Haiku build does something
> similar apparently.

I have to drag "far enough", so to speak, before the border actually
moves. Or put differently, when it moves, it's moving in whole character
steps.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#78418; Package emacs. (Tue, 20 May 2025 07:50:02 GMT) Full text and rfc822 format available.

Message #86 received at submit <at> debbugs.gnu.org (full text, mbox):

From: martin rudalics <rudalics <at> gmx.at>
To: Gerd Möllmann <gerd.moellmann <at> gmail.com>
Cc: yhaoxie <at> gmail.com, bug-gnu-emacs <at> gnu.org
Subject: Re: 31.0.50; Change in fit-frame-to-buffer doesn't work with
 transient-posframe
Date: Tue, 20 May 2025 09:49:44 +0200
> I have to drag "far enough", so to speak, before the border actually
> moves. Or put differently, when it moves, it's moving in whole character
> steps.

OK.  So the only remaining question is whether we should implement a
'resize-pixelwise' frame parameter.  It's tedious work, so I'll do it
only if someone wants it.  Whether 'frame-resize-pixelwise' should be
non-nil by default, I leave to others to decide.

martin




This bug report was last modified 82 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.