diff options
| author | Martin Rudalics | 2019-10-11 08:46:52 +0200 |
|---|---|---|
| committer | Martin Rudalics | 2019-10-11 08:46:52 +0200 |
| commit | e3f97d73653df725322d7f2392d36f858cce5a73 (patch) | |
| tree | a87da8ba408b52a7efccad07359412fd4e7cbe7a | |
| parent | fcfe6e279774b2e5100b0a660aaa3f3f75ed0a7a (diff) | |
| download | emacs-e3f97d73653df725322d7f2392d36f858cce5a73.tar.gz emacs-e3f97d73653df725322d7f2392d36f858cce5a73.zip | |
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.
| -rw-r--r-- | lisp/window.el | 252 |
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." | |||
| 8501 | (eobp) | 8501 | (eobp) |
| 8502 | window)))) | 8502 | window)))) |
| 8503 | 8503 | ||
| 8504 | (defun window-default-font-height (&optional window) | ||
| 8505 | "Return height in pixels of WINDOW's default face font. | ||
| 8506 | WINDOW must be a live window and defaults to the selected one. | ||
| 8507 | |||
| 8508 | The return value accounts for any remapping of the default face | ||
| 8509 | font on WINDOW's frame." | ||
| 8510 | (let* ((window (window-normalize-window window t)) | ||
| 8511 | (frame (window-frame window)) | ||
| 8512 | (default-font (face-font 'default frame))) | ||
| 8513 | (if (and (display-multi-font-p (frame-parameter frame 'display)) | ||
| 8514 | (not (string-equal (frame-parameter frame 'font) default-font))) | ||
| 8515 | (aref (font-info default-font frame) 3) | ||
| 8516 | (frame-char-height frame)))) | ||
| 8517 | |||
| 8518 | (defun window-default-line-height (&optional window) | ||
| 8519 | "Return height in pixels of a text line in WINDOW. | ||
| 8520 | WINDOW must be a live window and defaults to the selected one. | ||
| 8521 | |||
| 8522 | The return value includes any line spacing defined for WINDOW's | ||
| 8523 | buffer or frame and accounts for any remapping of the default | ||
| 8524 | face on WINDOW's frame." | ||
| 8525 | (let* ((window (window-normalize-window window t)) | ||
| 8526 | (font-height (window-default-font-height window)) | ||
| 8527 | (frame (window-frame window)) | ||
| 8528 | (buffer (window-buffer window)) | ||
| 8529 | (space-height | ||
| 8530 | (or (and (display-graphic-p frame) | ||
| 8531 | (or (buffer-local-value 'line-spacing buffer) | ||
| 8532 | (frame-parameter frame 'line-spacing))) | ||
| 8533 | 0))) | ||
| 8534 | (+ font-height | ||
| 8535 | (if (floatp space-height) | ||
| 8536 | (truncate (* (frame-char-height frame) space-height)) | ||
| 8537 | space-height)))) | ||
| 8538 | |||
| 8504 | ;;; Resizing windows and frames to fit their contents exactly. | 8539 | ;;; Resizing windows and frames to fit their contents exactly. |
| 8505 | (defcustom fit-window-to-buffer-horizontally nil | 8540 | (defcustom fit-window-to-buffer-horizontally nil |
| 8506 | "Non-nil means `fit-window-to-buffer' can resize windows horizontally. | 8541 | "Non-nil means `fit-window-to-buffer' can resize windows horizontally. |
| @@ -8643,6 +8678,7 @@ parameters of FRAME." | |||
| 8643 | (char-height (frame-char-height frame)) | 8678 | (char-height (frame-char-height frame)) |
| 8644 | ;; WINDOW is FRAME's root window. | 8679 | ;; WINDOW is FRAME's root window. |
| 8645 | (window (frame-root-window frame)) | 8680 | (window (frame-root-window frame)) |
| 8681 | (line-height (window-default-line-height window)) | ||
| 8646 | (parent (frame-parent frame)) | 8682 | (parent (frame-parent frame)) |
| 8647 | (monitor-attributes | 8683 | (monitor-attributes |
| 8648 | (unless parent | 8684 | (unless parent |
| @@ -8739,16 +8775,16 @@ parameters of FRAME." | |||
| 8739 | (max-height | 8775 | (max-height |
| 8740 | (min | 8776 | (min |
| 8741 | (cond | 8777 | (cond |
| 8742 | ((numberp max-height) (* max-height char-height)) | 8778 | ((numberp max-height) (* max-height line-height)) |
| 8743 | ((numberp (nth 0 sizes)) (* (nth 0 sizes) char-height)) | 8779 | ((numberp (nth 0 sizes)) (* (nth 0 sizes) line-height)) |
| 8744 | (t parent-or-display-height)) | 8780 | (t parent-or-display-height)) |
| 8745 | ;; The following is the maximum height that fits into the | 8781 | ;; The following is the maximum height that fits into the |
| 8746 | ;; top and bottom margins. | 8782 | ;; top and bottom margins. |
| 8747 | (max (- bottom-margin top-margin outer-minus-body-height)))) | 8783 | (max (- bottom-margin top-margin outer-minus-body-height)))) |
| 8748 | (min-height | 8784 | (min-height |
| 8749 | (cond | 8785 | (cond |
| 8750 | ((numberp min-height) (* min-height char-height)) | 8786 | ((numberp min-height) (* min-height line-height)) |
| 8751 | ((numberp (nth 1 sizes)) (* (nth 1 sizes) char-height)) | 8787 | ((numberp (nth 1 sizes)) (* (nth 1 sizes) line-height)) |
| 8752 | (t (window-min-size window nil nil t)))) | 8788 | (t (window-min-size window nil nil t)))) |
| 8753 | (max-width | 8789 | (max-width |
| 8754 | (min | 8790 | (min |
| @@ -8871,124 +8907,118 @@ accessible position." | |||
| 8871 | max-height min-height max-width min-width | 8907 | max-height min-height max-width min-width |
| 8872 | (and (memq fit-frame-to-buffer '(vertically horizontally)) | 8908 | (and (memq fit-frame-to-buffer '(vertically horizontally)) |
| 8873 | fit-frame-to-buffer))) | 8909 | fit-frame-to-buffer))) |
| 8874 | (with-selected-window window | 8910 | (let* ((pixelwise window-resize-pixelwise) |
| 8875 | (let* ((pixelwise window-resize-pixelwise) | 8911 | (frame (window-frame window)) |
| 8876 | (char-height (frame-char-height)) | 8912 | (char-height (frame-char-height frame))) |
| 8877 | (char-width (frame-char-width)) | 8913 | (cond |
| 8878 | (total-height (window-size window nil pixelwise)) | 8914 | ;; If WINDOW is vertically combined, try to resize it |
| 8879 | (body-height (window-body-height window pixelwise)) | 8915 | ;; vertically. |
| 8880 | (body-width (window-body-width window pixelwise)) | 8916 | ((and (not (eq fit-window-to-buffer-horizontally 'only)) |
| 8881 | (min-height | 8917 | (not (window-size-fixed-p window 'preserved)) |
| 8882 | ;; Sanitize MIN-HEIGHT. | 8918 | (window-combined-p)) |
| 8883 | (if (numberp min-height) | 8919 | (let* ((line-height (window-default-line-height window)) |
| 8884 | ;; Can't get smaller than `window-safe-min-height'. | 8920 | (total-height (window-size window nil pixelwise)) |
| 8885 | (max (if pixelwise | 8921 | (min-height |
| 8886 | (* char-height min-height) | 8922 | ;; Sanitize MIN-HEIGHT. |
| 8887 | min-height) | 8923 | (if (numberp min-height) |
| 8888 | (if pixelwise | 8924 | ;; Can't get smaller than `window-safe-min-height'. |
| 8889 | (window-safe-min-pixel-height window) | 8925 | (max (if pixelwise |
| 8890 | window-safe-min-height)) | 8926 | (* line-height min-height) |
| 8891 | ;; Preserve header and mode line if present. | 8927 | min-height) |
| 8892 | (max (if pixelwise | 8928 | (if pixelwise |
| 8893 | (* char-height window-min-height) | 8929 | (window-safe-min-pixel-height window) |
| 8894 | window-min-height) | 8930 | window-safe-min-height)) |
| 8895 | (window-min-size window nil window pixelwise)))) | 8931 | ;; Preserve header and mode line if present. |
| 8896 | (max-height | 8932 | (max (if pixelwise |
| 8897 | ;; Sanitize MAX-HEIGHT. | 8933 | (* line-height window-min-height) |
| 8898 | (if (numberp max-height) | 8934 | window-min-height) |
| 8899 | (min | 8935 | (window-min-size window nil window pixelwise)))) |
| 8900 | (+ total-height | 8936 | (max-height |
| 8901 | (window-max-delta | 8937 | ;; Sanitize MAX-HEIGHT. |
| 8902 | window nil window nil t nil pixelwise)) | 8938 | (if (numberp max-height) |
| 8903 | (if pixelwise | 8939 | (min |
| 8904 | (* char-height max-height) | 8940 | (+ total-height |
| 8905 | max-height)) | 8941 | (window-max-delta |
| 8906 | (+ total-height (window-max-delta | 8942 | window nil window nil t nil pixelwise)) |
| 8907 | window nil window nil t nil pixelwise)))) | 8943 | (if pixelwise |
| 8908 | height) | 8944 | (* line-height max-height) |
| 8909 | (cond | 8945 | (/ (* line-height max-height) line-height))) |
| 8910 | ;; If WINDOW is vertically combined, try to resize it | 8946 | (+ total-height (window-max-delta |
| 8911 | ;; vertically. | 8947 | window nil window nil t nil pixelwise)))) |
| 8912 | ((and (not (eq fit-window-to-buffer-horizontally 'only)) | 8948 | (height (+ (cdr (window-text-pixel-size |
| 8913 | (not (window-size-fixed-p window 'preserved)) | 8949 | window nil t nil (frame-pixel-height frame) t)) |
| 8914 | (window-combined-p)) | 8950 | (window-scroll-bar-height window) |
| 8951 | (window-bottom-divider-width window)))) | ||
| 8915 | ;; Vertically we always want to fit the entire buffer. | 8952 | ;; Vertically we always want to fit the entire buffer. |
| 8916 | ;; WINDOW'S height can't get larger than its frame's pixel | 8953 | ;; WINDOW'S height can't get larger than its frame's pixel |
| 8917 | ;; height. Its width remains fixed. | 8954 | ;; height. Its width remains fixed. |
| 8918 | (setq height (+ (cdr (window-text-pixel-size | ||
| 8919 | nil nil t nil (frame-pixel-height) t)) | ||
| 8920 | (window-scroll-bar-height window) | ||
| 8921 | (window-bottom-divider-width))) | ||
| 8922 | ;; Round height. | 8955 | ;; Round height. |
| 8923 | (unless pixelwise | 8956 | (unless pixelwise |
| 8924 | (setq height (/ (+ height char-height -1) char-height))) | 8957 | (setq height (/ (+ height char-height -1) char-height))) |
| 8958 | (setq height (max min-height (min max-height height))) | ||
| 8925 | (unless (= height total-height) | 8959 | (unless (= height total-height) |
| 8926 | (window-preserve-size window) | 8960 | (window-preserve-size window) |
| 8927 | (window-resize-no-error | 8961 | (window-resize-no-error |
| 8928 | window | 8962 | window (- height total-height) nil window pixelwise) |
| 8929 | (- (max min-height (min max-height height)) total-height) | ||
| 8930 | nil window pixelwise) | ||
| 8931 | (when preserve-size | 8963 | (when preserve-size |
| 8932 | (window-preserve-size window nil t)))) | 8964 | (window-preserve-size window nil t))))) |
| 8933 | ;; If WINDOW is horizontally combined, try to resize it | 8965 | ;; If WINDOW is horizontally combined, try to resize it |
| 8934 | ;; horizontally. | 8966 | ;; horizontally. |
| 8935 | ((and fit-window-to-buffer-horizontally | 8967 | ((and fit-window-to-buffer-horizontally |
| 8936 | (not (window-size-fixed-p window t 'preserved)) | 8968 | (not (window-size-fixed-p window t 'preserved)) |
| 8937 | (window-combined-p nil t)) | 8969 | (window-combined-p window t)) |
| 8938 | (let* ((total-width (window-size window t pixelwise)) | 8970 | (let* ((char-width (frame-char-width frame)) |
| 8939 | (min-width | 8971 | (total-width (window-size window t pixelwise)) |
| 8940 | ;; Sanitize MIN-WIDTH. | 8972 | (min-width |
| 8941 | (if (numberp min-width) | 8973 | ;; Sanitize MIN-WIDTH. |
| 8942 | ;; Can't get smaller than `window-safe-min-width'. | 8974 | (if (numberp min-width) |
| 8943 | (max (if pixelwise | 8975 | ;; Can't get smaller than `window-safe-min-width'. |
| 8944 | (* char-width min-width) | ||
| 8945 | min-width) | ||
| 8946 | (if pixelwise | ||
| 8947 | (window-safe-min-pixel-width) | ||
| 8948 | window-safe-min-width)) | ||
| 8949 | ;; Preserve fringes, margins, scrollbars if present. | ||
| 8950 | (max (if pixelwise | 8976 | (max (if pixelwise |
| 8951 | (* char-width window-min-width) | 8977 | (* char-width min-width) |
| 8952 | window-min-width) | 8978 | min-width) |
| 8953 | (window-min-size nil nil window pixelwise)))) | 8979 | (if pixelwise |
| 8954 | (max-width | 8980 | (window-safe-min-pixel-width window) |
| 8955 | ;; Sanitize MAX-WIDTH. | 8981 | window-safe-min-width)) |
| 8956 | (if (numberp max-width) | 8982 | ;; Preserve fringes, margins, scrollbars if present. |
| 8957 | (min (+ total-width | 8983 | (max (if pixelwise |
| 8958 | (window-max-delta | 8984 | (* char-width window-min-width) |
| 8959 | window t window nil t nil pixelwise)) | 8985 | window-min-width) |
| 8960 | (if pixelwise | 8986 | (window-min-size window nil window pixelwise)))) |
| 8961 | (* char-width max-width) | 8987 | (max-width |
| 8962 | max-width)) | 8988 | ;; Sanitize MAX-WIDTH. |
| 8963 | (+ total-width (window-max-delta | 8989 | (if (numberp max-width) |
| 8964 | window t window nil t nil pixelwise)))) | 8990 | (min (+ total-width |
| 8965 | ;; When fitting horizontally, assume that WINDOW's | 8991 | (window-max-delta |
| 8966 | ;; start position remains unaltered. WINDOW can't get | 8992 | window t window nil t nil pixelwise)) |
| 8967 | ;; wider than its frame's pixel width, its height | 8993 | (if pixelwise |
| 8968 | ;; remains unaltered. | 8994 | (* char-width max-width) |
| 8969 | (width (+ (car (window-text-pixel-size | 8995 | max-width)) |
| 8970 | nil (window-start) (point-max) | 8996 | (+ total-width (window-max-delta |
| 8971 | (frame-pixel-width) | 8997 | window t window nil t nil pixelwise)))) |
| 8972 | ;; Add one char-height to assure that | 8998 | ;; When fitting horizontally, assume that WINDOW's |
| 8973 | ;; we're on the safe side. This | 8999 | ;; start position remains unaltered. WINDOW can't get |
| 8974 | ;; overshoots when the first line below | 9000 | ;; wider than its frame's pixel width, its height |
| 8975 | ;; the bottom is wider than the window. | 9001 | ;; remains unaltered. |
| 8976 | (* body-height | 9002 | (width (+ (car (window-text-pixel-size |
| 8977 | (if pixelwise 1 char-height)))) | 9003 | window (window-start) (point-max) |
| 8978 | (window-right-divider-width)))) | 9004 | (frame-pixel-width) |
| 8979 | (unless pixelwise | 9005 | ;; Add one line-height to assure that |
| 8980 | (setq width (/ (+ width char-width -1) char-width))) | 9006 | ;; we're on the safe side. This |
| 8981 | (unless (= width body-width) | 9007 | ;; overshoots when the first line below |
| 8982 | (window-preserve-size window t) | 9008 | ;; the bottom is wider than the window. |
| 8983 | (window-resize-no-error | 9009 | (* (window-body-height window pixelwise) |
| 8984 | window | 9010 | (if pixelwise 1 char-height)))) |
| 8985 | (- (max min-width | 9011 | (- total-width |
| 8986 | (min max-width | 9012 | (window-body-width window pixelwise))))) |
| 8987 | (+ total-width (- width body-width)))) | 9013 | (unless pixelwise |
| 8988 | total-width) | 9014 | (setq width (/ (+ width char-width -1) char-width))) |
| 8989 | t window pixelwise) | 9015 | (setq width (max min-width (min max-width width))) |
| 8990 | (when preserve-size | 9016 | (unless (= width total-width) |
| 8991 | (window-preserve-size window t t)))))))))) | 9017 | (window-preserve-size window t) |
| 9018 | (window-resize-no-error | ||
| 9019 | window (- width total-width) t window pixelwise) | ||
| 9020 | (when preserve-size | ||
| 9021 | (window-preserve-size window t t))))))))) | ||
| 8992 | 9022 | ||
| 8993 | (defun window-safely-shrinkable-p (&optional window) | 9023 | (defun window-safely-shrinkable-p (&optional window) |
| 8994 | "Return t if WINDOW can be shrunk without shrinking other windows. | 9024 | "Return t if WINDOW can be shrunk without shrinking other windows. |