+ (when (and (window-live-p (frame-root-window frame))
+ fit-frame-to-buffer
+ (or (not window-size-fixed)
+ (and (eq window-size-fixed 'height)
+ (not (eq fit-frame-to-buffer 'vertically)))
+ (and (eq window-size-fixed 'width)
+ (not (eq fit-frame-to-buffer 'horizontally)))))
+ (with-selected-window (frame-root-window frame)
+ (let* ((window (frame-root-window frame))
+ (char-width (frame-char-width))
+ (char-height (frame-char-height))
+ (monitor-attributes (car (display-monitor-attributes-list
+ (frame-parameter frame 'display))))
+ (geometry (cdr (assq 'geometry monitor-attributes)))
+ (display-width (- (nth 2 geometry) (nth 0 geometry)))
+ (display-height (- (nth 3 geometry) (nth 1 geometry)))
+ (workarea (cdr (assq 'workarea monitor-attributes)))
+ ;; Handle margins.
+ (margins (or (frame-parameter frame 'fit-frame-to-buffer-margins)
+ fit-frame-to-buffer-margins))
+ (left-margin (or (window--sanitize-margin
+ (nth 0 margins) 0 display-width)
+ (nth 0 workarea)))
+ (top-margin (or (window--sanitize-margin
+ (nth 1 margins) 0 display-height)
+ (nth 1 workarea)))
+ (workarea-width (nth 2 workarea))
+ (right-margin (or (window--sanitize-margin
+ (nth 2 margins) left-margin display-width)
+ (+ left-margin workarea-width)))
+ (workarea-height (nth 3 workarea))
+ (bottom-margin (or (window--sanitize-margin
+ (nth 3 margins) top-margin display-height)
+ (+ top-margin workarea-height)))
+ ;; The pixel width of FRAME (which does not include the
+ ;; window manager's decorations).
+ (frame-width (frame-pixel-width))
+ ;; The pixel width of the body of FRAME's root window.
+ (window-body-width (window-body-width nil t))
+ ;; The difference in pixels between total and body width of
+ ;; FRAME's window.
+ (window-extra-width (- (window-pixel-width) window-body-width))
+ ;; The difference in pixels between the frame's pixel width
+ ;; and the window's body width. This is the space we can't
+ ;; use for fitting.
+ (extra-width (- frame-width window-body-width))
+ ;; The maximum width we can use for fitting.
+ (fit-width (- workarea-width extra-width))
+ ;; The pixel position of FRAME's left border. We usually
+ ;; try to leave this alone.
+ (left
+ (let ((left (frame-parameter nil 'left)))
+ (if (consp left)
+ (funcall (car left) (cadr left))
+ left)))
+ ;; The pixel height of FRAME (which does not include title
+ ;; line, decorations, and sometimes neither the menu nor
+ ;; the toolbar).
+ (frame-height (frame-pixel-height))
+ ;; The pixel height of FRAME's root window (we don't care
+ ;; about the window's body height since the return value of
+ ;; `window-text-pixel-size' includes header and mode line).
+ (window-height (window-pixel-height))
+ ;; The difference in pixels between the frame's pixel
+ ;; height and the window's height.
+ (extra-height (- frame-height window-height))
+ ;; When tool-bar-mode is enabled and we just created a new
+ ;; frame, reserve lines for toolbar resizing. Needed
+ ;; because for reasons unknown to me Emacs (1) reserves one
+ ;; line for the toolbar when making the initial frame and
+ ;; toolbars are enabled, and (2) later adds the remaining
+ ;; lines needed. Our code runs IN BETWEEN (1) and (2).
+ ;; YMMV when you're on a system that behaves differently.
+ (toolbar-extra-height
+ (let ((quit-restore (window-parameter window 'quit-restore))
+ ;; This may have to change when we allow arbitrary
+ ;; pixel height toolbars.
+ (lines (tool-bar-height)))
+ (* char-height
+ (if (and quit-restore (eq (car quit-restore) 'frame)
+ (not (zerop lines)))
+ (1- lines)
+ 0))))
+ ;; The maximum height we can use for fitting.
+ (fit-height
+ (- workarea-height extra-height toolbar-extra-height))
+ ;; The pixel position of FRAME's top border. We usually
+ ;; try to leave this alone.
+ (top
+ (let ((top (frame-parameter nil 'top)))
+ (if (consp top)
+ (funcall (car top) (cadr top))
+ top)))
+ ;; Sanitize minimum and maximum sizes.
+ (sizes (or (frame-parameter frame 'fit-frame-to-buffer-sizes)
+ fit-frame-to-buffer-sizes))
+ (max-height
+ (cond
+ ((numberp (nth 0 sizes)) (* (nth 0 sizes) char-height))
+ ((numberp max-height) (* max-height char-height))))
+ (min-height
+ (cond
+ ((numberp (nth 1 sizes)) (* (nth 1 sizes) char-height))
+ ((numberp min-height) (* min-height char-height))
+ (t (* window-min-height char-height))))
+ (max-width
+ (cond
+ ((numberp (nth 2 sizes))
+ (- (* (nth 2 sizes) char-width) window-extra-width))
+ ((numberp max-width)
+ (- (* max-width char-width) window-extra-width))))
+ (min-width
+ (cond
+ ((numberp (nth 3 sizes))
+ (- (* (nth 3 sizes) char-width) window-extra-width))
+ ((numberp min-width)
+ (- (* min-width char-width) window-extra-width))
+ (t (* window-min-width char-width))))
+ ;; Note: Currently, for a new frame the sizes of the header
+ ;; and mode line may be estimated incorrectly
+ (value (window-text-pixel-size
+ nil t t workarea-width workarea-height t))
+ (width (+ (car value) (window-right-divider-width)))
+ (height (+ (cdr value) (window-bottom-divider-width)))
+ remainder)
+ (unless frame-resize-pixelwise
+ ;; Round sizes to character sizes.
+ (setq remainder (% width char-width))
+ (unless (zerop remainder)
+ (setq width (+ width (- char-width remainder))))
+ (setq remainder (% height char-height))
+ (setq height (+ height (- char-height remainder))))
+ ;; Now make sure that we don't get larger than our rounded
+ ;; maximum lines and columns.
+ (when (> width fit-width)
+ (setq width (- fit-width (% fit-width char-width))))
+ (when (> height fit-height)
+ (setq height (- fit-height (% fit-height char-height))))
+ ;; Don't change height or width when the window's size is fixed
+ ;; in either direction.