From: martin rudalics <rudalics@gmx.at>
To: Ingo Lohmar <ingo.lohmar@posteo.net>
Cc: 37563@debbugs.gnu.org
Subject: bug#37563: 27.0.50; fit-frame-to-buffer does not account for line-spacing
Date: Mon, 7 Oct 2019 11:25:52 +0200 [thread overview]
Message-ID: <b3244e84-fea8-6f09-9054-a470c5bbed03@gmx.at> (raw)
In-Reply-To: <87a7af7eb5.fsf@kenko.localhost.com>
[-- Attachment #1: Type: text/plain, Size: 1577 bytes --]
I now came up with a fix for 'fit-window-to-buffer' too which had some
strange misbehavior with different size restricting arguments when the
window's text size did not change. See attached diffs and Change Log
below.
> I think I understand better now, I was hampered by some weird debugging
> artifacts in my current setup. With the default
> `frame-resize-pixelwise' of nil, and the otherwise bug-fixed code,
> nothing is cut off, but there is some slack whitespace, indeed.
I suppose that part of that whitespace comes from the fact that with
'line-spacing' greater zero, 'window-text-pixel-size' includes the
space below the last line of its text. It would be nice to get rid of
that but ISTR that a line's text may now get centered within the space
reserved for it. So I cannot just remove the entire line space of one
line from the return value but probably only half of the line spacing
value. How would I know the right value?
martin
Fixes for fitting windows and frames to their buffers (Bug#37563)
* lisp/window.el (window-default-font-height)
(window-default-line-height): New functions.
(fit-frame-to-buffer): Interpret values of MAX-HEIGHT and
MIN-HEIGHT arguments in terms of WINDOW's default line height
(Bug#37563).
(fit-window-to-buffer): Obey size restricting arguments even
when size of WINDOW's text does not change. Do not
temporarily select WINDOW and perform height/width related
calculations if and only if WINDOW is accordingly combined.
Interpret values of MAX-HEIGHT and MIN-HEIGHT arguments in
terms of WINDOW's default line height.
[-- Attachment #2: fit-to-buffer.diffs --]
[-- Type: text/plain, Size: 12028 bytes --]
diff --git a/lisp/window.el b/lisp/window.el
index d93ec0add6..fafb6f90ed 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -8501,6 +8501,41 @@ window-buffer-height
(eobp)
window))))
+(defun window-default-font-height (&optional window)
+ "Return height in pixels of WINDOW's default face font.
+WINDOW must be a live window and defaults to the selected one.
+
+The return value accounts for any remapping of the default face
+font on WINDOW's frame."
+ (let* ((window (window-normalize-window window t))
+ (frame (window-frame window))
+ (default-font (face-font 'default frame)))
+ (if (and (display-multi-font-p (frame-parameter frame 'display))
+ (not (string-equal (frame-parameter frame 'font) default-font)))
+ (aref (font-info default-font frame) 3)
+ (frame-char-height frame))))
+
+(defun window-default-line-height (&optional window)
+ "Return height in pixels of a text line in WINDOW.
+WINDOW must be a live window and defaults to the selected one.
+
+The return value includes any line spacing defined for WINDOW's
+buffer or frame and accounts for any remapping of the default
+face on WINDOW's frame."
+ (let* ((window (window-normalize-window window t))
+ (font-height (window-default-font-height window))
+ (frame (window-frame window))
+ (buffer (window-buffer window))
+ (space-height
+ (or (and (display-graphic-p frame)
+ (or (buffer-local-value 'line-spacing buffer)
+ (frame-parameter frame 'line-spacing)))
+ 0)))
+ (+ font-height
+ (if (floatp space-height)
+ (truncate (* (frame-char-height frame) space-height))
+ space-height))))
+
;;; Resizing windows and frames to fit their contents exactly.
(defcustom fit-window-to-buffer-horizontally nil
"Non-nil means `fit-window-to-buffer' can resize windows horizontally.
@@ -8643,6 +8678,7 @@ fit-frame-to-buffer
(char-height (frame-char-height frame))
;; WINDOW is FRAME's root window.
(window (frame-root-window frame))
+ (line-height (window-default-line-height window))
(parent (frame-parent frame))
(monitor-attributes
(unless parent
@@ -8739,16 +8775,16 @@ fit-frame-to-buffer
(max-height
(min
(cond
- ((numberp max-height) (* max-height char-height))
- ((numberp (nth 0 sizes)) (* (nth 0 sizes) char-height))
+ ((numberp max-height) (* max-height line-height))
+ ((numberp (nth 0 sizes)) (* (nth 0 sizes) line-height))
(t parent-or-display-height))
;; The following is the maximum height that fits into the
;; top and bottom margins.
(max (- bottom-margin top-margin outer-minus-body-height))))
(min-height
(cond
- ((numberp min-height) (* min-height char-height))
- ((numberp (nth 1 sizes)) (* (nth 1 sizes) char-height))
+ ((numberp min-height) (* min-height line-height))
+ ((numberp (nth 1 sizes)) (* (nth 1 sizes) line-height))
(t (window-min-size window nil nil t))))
(max-width
(min
@@ -8871,124 +8907,118 @@ fit-window-to-buffer
max-height min-height max-width min-width
(and (memq fit-frame-to-buffer '(vertically horizontally))
fit-frame-to-buffer)))
- (with-selected-window window
- (let* ((pixelwise window-resize-pixelwise)
- (char-height (frame-char-height))
- (char-width (frame-char-width))
- (total-height (window-size window nil pixelwise))
- (body-height (window-body-height window pixelwise))
- (body-width (window-body-width window pixelwise))
- (min-height
- ;; Sanitize MIN-HEIGHT.
- (if (numberp min-height)
- ;; Can't get smaller than `window-safe-min-height'.
- (max (if pixelwise
- (* char-height min-height)
- min-height)
- (if pixelwise
- (window-safe-min-pixel-height window)
- window-safe-min-height))
- ;; Preserve header and mode line if present.
- (max (if pixelwise
- (* char-height window-min-height)
- window-min-height)
- (window-min-size window nil window pixelwise))))
- (max-height
- ;; Sanitize MAX-HEIGHT.
- (if (numberp max-height)
- (min
- (+ total-height
- (window-max-delta
- window nil window nil t nil pixelwise))
- (if pixelwise
- (* char-height max-height)
- max-height))
- (+ total-height (window-max-delta
- window nil window nil t nil pixelwise))))
- height)
- (cond
- ;; If WINDOW is vertically combined, try to resize it
- ;; vertically.
- ((and (not (eq fit-window-to-buffer-horizontally 'only))
- (not (window-size-fixed-p window 'preserved))
- (window-combined-p))
+ (let* ((pixelwise window-resize-pixelwise)
+ (frame (window-frame window))
+ (char-height (frame-char-height frame)))
+ (cond
+ ;; If WINDOW is vertically combined, try to resize it
+ ;; vertically.
+ ((and (not (eq fit-window-to-buffer-horizontally 'only))
+ (not (window-size-fixed-p window 'preserved))
+ (window-combined-p))
+ (let* ((line-height (window-default-line-height window))
+ (total-height (window-size window nil pixelwise))
+ (min-height
+ ;; Sanitize MIN-HEIGHT.
+ (if (numberp min-height)
+ ;; Can't get smaller than `window-safe-min-height'.
+ (max (if pixelwise
+ (* line-height min-height)
+ min-height)
+ (if pixelwise
+ (window-safe-min-pixel-height window)
+ window-safe-min-height))
+ ;; Preserve header and mode line if present.
+ (max (if pixelwise
+ (* line-height window-min-height)
+ window-min-height)
+ (window-min-size window nil window pixelwise))))
+ (max-height
+ ;; Sanitize MAX-HEIGHT.
+ (if (numberp max-height)
+ (min
+ (+ total-height
+ (window-max-delta
+ window nil window nil t nil pixelwise))
+ (if pixelwise
+ (* line-height max-height)
+ (/ (* line-height max-height) line-height)))
+ (+ total-height (window-max-delta
+ window nil window nil t nil pixelwise))))
+ (height (+ (cdr (window-text-pixel-size
+ window nil t nil (frame-pixel-height frame) t))
+ (window-scroll-bar-height window)
+ (window-bottom-divider-width window))))
;; Vertically we always want to fit the entire buffer.
;; WINDOW'S height can't get larger than its frame's pixel
;; height. Its width remains fixed.
- (setq height (+ (cdr (window-text-pixel-size
- nil nil t nil (frame-pixel-height) t))
- (window-scroll-bar-height window)
- (window-bottom-divider-width)))
;; Round height.
(unless pixelwise
(setq height (/ (+ height char-height -1) char-height)))
+ (setq height (max min-height (min max-height height)))
(unless (= height total-height)
(window-preserve-size window)
(window-resize-no-error
- window
- (- (max min-height (min max-height height)) total-height)
- nil window pixelwise)
+ window (- height total-height) nil window pixelwise)
(when preserve-size
- (window-preserve-size window nil t))))
- ;; If WINDOW is horizontally combined, try to resize it
- ;; horizontally.
- ((and fit-window-to-buffer-horizontally
- (not (window-size-fixed-p window t 'preserved))
- (window-combined-p nil t))
- (let* ((total-width (window-size window t pixelwise))
- (min-width
- ;; Sanitize MIN-WIDTH.
- (if (numberp min-width)
- ;; Can't get smaller than `window-safe-min-width'.
- (max (if pixelwise
- (* char-width min-width)
- min-width)
- (if pixelwise
- (window-safe-min-pixel-width)
- window-safe-min-width))
- ;; Preserve fringes, margins, scrollbars if present.
+ (window-preserve-size window nil t)))))
+ ;; If WINDOW is horizontally combined, try to resize it
+ ;; horizontally.
+ ((and fit-window-to-buffer-horizontally
+ (not (window-size-fixed-p window t 'preserved))
+ (window-combined-p window t))
+ (let* ((char-width (frame-char-width frame))
+ (total-width (window-size window t pixelwise))
+ (min-width
+ ;; Sanitize MIN-WIDTH.
+ (if (numberp min-width)
+ ;; Can't get smaller than `window-safe-min-width'.
(max (if pixelwise
- (* char-width window-min-width)
- window-min-width)
- (window-min-size nil nil window pixelwise))))
- (max-width
- ;; Sanitize MAX-WIDTH.
- (if (numberp max-width)
- (min (+ total-width
- (window-max-delta
- window t window nil t nil pixelwise))
- (if pixelwise
- (* char-width max-width)
- max-width))
- (+ total-width (window-max-delta
- window t window nil t nil pixelwise))))
- ;; When fitting horizontally, assume that WINDOW's
- ;; start position remains unaltered. WINDOW can't get
- ;; wider than its frame's pixel width, its height
- ;; remains unaltered.
- (width (+ (car (window-text-pixel-size
- nil (window-start) (point-max)
- (frame-pixel-width)
- ;; Add one char-height to assure that
- ;; we're on the safe side. This
- ;; overshoots when the first line below
- ;; the bottom is wider than the window.
- (* body-height
- (if pixelwise 1 char-height))))
- (window-right-divider-width))))
- (unless pixelwise
- (setq width (/ (+ width char-width -1) char-width)))
- (unless (= width body-width)
- (window-preserve-size window t)
- (window-resize-no-error
- window
- (- (max min-width
- (min max-width
- (+ total-width (- width body-width))))
- total-width)
- t window pixelwise)
- (when preserve-size
- (window-preserve-size window t t))))))))))
+ (* char-width min-width)
+ min-width)
+ (if pixelwise
+ (window-safe-min-pixel-width window)
+ window-safe-min-width))
+ ;; Preserve fringes, margins, scrollbars if present.
+ (max (if pixelwise
+ (* char-width window-min-width)
+ window-min-width)
+ (window-min-size window nil window pixelwise))))
+ (max-width
+ ;; Sanitize MAX-WIDTH.
+ (if (numberp max-width)
+ (min (+ total-width
+ (window-max-delta
+ window t window nil t nil pixelwise))
+ (if pixelwise
+ (* char-width max-width)
+ max-width))
+ (+ total-width (window-max-delta
+ window t window nil t nil pixelwise))))
+ ;; When fitting horizontally, assume that WINDOW's
+ ;; start position remains unaltered. WINDOW can't get
+ ;; wider than its frame's pixel width, its height
+ ;; remains unaltered.
+ (width (+ (car (window-text-pixel-size
+ window (window-start) (point-max)
+ (frame-pixel-width)
+ ;; Add one line-height to assure that
+ ;; we're on the safe side. This
+ ;; overshoots when the first line below
+ ;; the bottom is wider than the window.
+ (* (window-body-height window pixelwise)
+ (if pixelwise 1 char-height))))
+ (- total-width
+ (window-body-width window pixelwise)))))
+ (unless pixelwise
+ (setq width (/ (+ width char-width -1) char-width)))
+ (setq width (max min-width (min max-width width)))
+ (unless (= width total-width)
+ (window-preserve-size window t)
+ (window-resize-no-error
+ window (- width total-width) t window pixelwise)
+ (when preserve-size
+ (window-preserve-size window t t)))))))))
(defun window-safely-shrinkable-p (&optional window)
"Return t if WINDOW can be shrunk without shrinking other windows.
next prev parent reply other threads:[~2019-10-07 9:25 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-09-30 18:41 bug#37563: 27.0.50; fit-frame-to-buffer does not account for line-spacing Ingo Lohmar
2019-10-01 7:32 ` martin rudalics
[not found] ` <87lfu4aook.fsf@kenko.localhost.com>
2019-10-01 8:10 ` martin rudalics
2019-10-01 8:28 ` Ingo Lohmar
2019-10-02 8:54 ` martin rudalics
2019-10-03 8:15 ` martin rudalics
2019-10-03 8:48 ` Ingo Lohmar
2019-10-03 18:10 ` martin rudalics
2019-10-03 18:21 ` Ingo Lohmar
2019-10-05 8:41 ` martin rudalics
2019-10-05 9:05 ` Ingo Lohmar
2019-10-07 9:25 ` martin rudalics [this message]
2019-10-07 17:45 ` Ingo Lohmar
2019-10-08 8:44 ` martin rudalics
2019-10-11 8:16 ` martin rudalics
2019-10-11 17:45 ` Ingo Lohmar
2019-10-03 8:56 ` Ingo Lohmar
2019-10-03 9:12 ` Robert Pluim
2019-10-03 16:09 ` Eli Zaretskii
2019-10-03 18:10 ` martin rudalics
2019-10-03 18:22 ` Ingo Lohmar
2019-10-01 7:39 ` bug#37563: [PATCH] please review Ingo Lohmar
2019-10-02 8:53 ` martin rudalics
[not found] ` <handler.37563.B.156987198814967.ack@debbugs.gnu.org>
2019-10-11 17:50 ` bug#37563: Acknowledgement (27.0.50; fit-frame-to-buffer does not account for line-spacing) Ingo Lohmar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b3244e84-fea8-6f09-9054-a470c5bbed03@gmx.at \
--to=rudalics@gmx.at \
--cc=37563@debbugs.gnu.org \
--cc=ingo.lohmar@posteo.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).