summaryrefslogtreecommitdiff
path: root/lisp/window.el
diff options
context:
space:
mode:
authorMartin Rudalics <rudalics@gmx.at>2019-10-11 08:46:52 +0200
committerMartin Rudalics <rudalics@gmx.at>2019-10-11 08:46:52 +0200
commite3f97d73653df725322d7f2392d36f858cce5a73 (patch)
treea87da8ba408b52a7efccad07359412fd4e7cbe7a /lisp/window.el
parentfcfe6e279774b2e5100b0a660aaa3f3f75ed0a7a (diff)
downloademacs-e3f97d73653df725322d7f2392d36f858cce5a73.tar.gz
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.
Diffstat (limited to 'lisp/window.el')
-rw-r--r--lisp/window.el252
1 files changed, 141 insertions, 111 deletions
diff --git a/lisp/window.el b/lisp/window.el
index d93ec0add67..fafb6f90ed5 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -8501,6 +8501,41 @@ WINDOW must be a live window and defaults to the selected one."
(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 @@ parameters of FRAME."
(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 @@ parameters of FRAME."
(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 @@ accessible position."
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.