(window-make-atom (window-parent window))
;; Display BUFFER in NEW and return NEW.
(window--display-buffer
- buffer new 'window display-buffer-mark-dedicated))))
+ buffer new 'window alist display-buffer-mark-dedicated))))
(defun window--atom-check-1 (window)
"Subroutine of `window--atom-check'."
SIDE. Return the new window, nil if its creation window failed."
(let* ((root (frame-root-window))
(left-or-right (memq side '(left right)))
- (size (or (assq 'size alist)
- (/ (window-total-size (frame-root-window) left-or-right)
- ;; By default use a fourth of the size of the
- ;; frame's root window. This has to be made
- ;; customizable via ALIST.
- 4)))
(major (window--major-side-window side))
(selected-window (selected-window))
(on-side (cond
;; parent window unless needed.
(window-combination-resize 'side)
(window-combination-limit nil)
- (new (split-window major (- size) on-side))
+ (new (split-window major nil on-side))
fun)
(when new
;; Initialize `window-side' parameter of new window to SIDE.
;; the new window is deleted, a side window on the opposite side
;; does not get resized.
(set-window-parameter new 'delete-window 'delete-side-window)
+ ;; Auto-adjust height/width of new window unless a size has been
+ ;; explicitly requested.
+ (unless (if left-or-right
+ (cdr (assq 'window-width alist))
+ (cdr (assq 'window-height alist)))
+ (setq alist
+ (cons
+ (cons
+ (if left-or-right 'window-width 'window-height)
+ (/ (window-total-size (frame-root-window) left-or-right)
+ ;; By default use a fourth of the size of the
+ ;; frame's root window.
+ 4))
+ alist)))
;; Install BUFFER in new window and return NEW.
- (window--display-buffer buffer new 'window 'side))))
+ (window--display-buffer buffer new 'window alist 'side))))
(defun delete-side-window (window)
"Delete side window WINDOW."
;; ALIST (or, better, avoided in the "other" functions).
(or (and this-window
;; Reuse `this-window'.
- (window--display-buffer buffer this-window 'reuse 'side))
+ (window--display-buffer buffer this-window 'reuse alist 'side))
(and (or (not max-slots) (< slots max-slots))
(or (and next-window
;; Make new window before `next-window'.
window 'delete-window 'delete-side-window)
window)))
(set-window-parameter window 'window-slot slot)
- (window--display-buffer buffer window 'window 'side))
+ (window--display-buffer buffer window 'window alist 'side))
(and best-window
;; Reuse `best-window'.
(progn
;; Give best-window the new slot value.
(set-window-parameter best-window 'window-slot slot)
- (window--display-buffer buffer best-window 'reuse 'side)))))))))
+ (window--display-buffer
+ buffer best-window 'reuse alist 'side)))))))))
(defun window--side-check (&optional frame)
"Check the side window configuration of FRAME.
(with-selected-window window
(split-window-below))))))))
-(defun window--try-to-split-window (window)
+(defun window--try-to-split-window (window &optional alist)
"Try to split WINDOW.
Return value returned by `split-window-preferred-function' if it
represents a live window, nil otherwise."
(not (frame-parameter (window-frame window) 'unsplittable))
(let* ((window-combination-limit
;; When `window-combination-limit' equals
- ;; `display-buffer' bind it to t so resizing steals
- ;; space preferably from the window that was split.
- (if (eq window-combination-limit 'display-buffer)
+ ;; `display-buffer' or equals `resize-window' and a
+ ;; `window-height' or `window-width' alist entry are
+ ;; present, bind it to t so resizing steals space
+ ;; preferably from the window that was split.
+ (if (or (eq window-combination-limit 'display-buffer)
+ (and (eq window-combination-limit 'window-size)
+ (or (cdr (assq 'window-height alist))
+ (cdr (assq 'window-width alist)))))
t
window-combination-limit))
(new-window
(/ (- (window-total-height window) (window-total-height)) 2))
(error nil))))
-(defun window--display-buffer (buffer window type &optional dedicated)
+(defun window--display-buffer (buffer window type &optional alist dedicated)
"Display BUFFER in WINDOW and make its frame visible.
TYPE must be one of the symbols `reuse', `window' or `frame' and
is passed unaltered to `display-buffer-record-window'. Set
(set-window-dedicated-p window dedicated))
(when (memq type '(window frame))
(set-window-prev-buffers window nil)))
+ (let ((parameter (window-parameter window 'quit-restore))
+ (height (cdr (assq 'window-height alist)))
+ (width (cdr (assq 'window-width alist))))
+ (when (or (memq type '(window frame))
+ (and (eq (car parameter) 'same)
+ (memq (nth 1 parameter) '(window frame))))
+ ;; Adjust height of new window or frame.
+ (cond
+ ((not height))
+ ((numberp height)
+ (let* ((new-height
+ (if (integerp height)
+ height
+ (round
+ (* (window-total-size (frame-root-window window))
+ height))))
+ (delta (- new-height (window-total-size window))))
+ (cond
+ ((and (window-resizable-p window delta nil 'safe)
+ (window-combined-p window))
+ (window-resize window delta nil 'safe))
+ ((or (eq type 'frame)
+ (and (eq (car parameter) 'same)
+ (eq (nth 1 parameter) 'frame)))
+ (set-frame-height
+ (window-frame window)
+ (+ (frame-height (window-frame window)) delta))))))
+ ((functionp height)
+ (ignore-errors (funcall height window))))
+ ;; Adjust width of a window or frame.
+ (cond
+ ((not width))
+ ((numberp width)
+ (let* ((new-width
+ (if (integerp width)
+ width
+ (round
+ (* (window-total-size (frame-root-window window) t)
+ width))))
+ (delta (- new-width (window-total-size window t))))
+ (cond
+ ((and (window-resizable-p window delta t 'safe)
+ (window-combined-p window t))
+ (window-resize window delta t 'safe))
+ ((or (eq type 'frame)
+ (and (eq (car parameter) 'same)
+ (eq (nth 1 parameter) 'frame)))
+ (set-frame-width
+ (window-frame window)
+ (+ (frame-width (window-frame window)) delta))))))
+ ((functionp width)
+ (ignore-errors (funcall width window))))))
window))
(defun window--maybe-raise-frame (frame)
(unless (or (cdr (assq 'inhibit-same-window alist))
(window-minibuffer-p)
(window-dedicated-p))
- (window--display-buffer buffer (selected-window) 'reuse)))
+ (window--display-buffer buffer (selected-window) 'reuse alist)))
(defun display-buffer--maybe-same-window (buffer alist)
"Conditionally display BUFFER in the selected window.
(get-buffer-window-list buffer 'nomini
frames))))))
(when (window-live-p window)
- (prog1 (window--display-buffer buffer window 'reuse)
+ (prog1 (window--display-buffer buffer window 'reuse alist)
(unless (cdr (assq 'inhibit-switch-frame alist))
(window--maybe-raise-frame (window-frame window)))))))
(when (and fun
(setq frame (funcall fun))
(setq window (frame-selected-window frame)))
- (prog1 (window--display-buffer buffer window
- 'frame display-buffer-mark-dedicated)
+ (prog1 (window--display-buffer
+ buffer window 'frame alist display-buffer-mark-dedicated)
(unless (cdr (assq 'inhibit-switch-frame alist))
(window--maybe-raise-frame frame))))))
(not (frame-parameter frame 'unsplittable))))
;; Attempt to split largest or least recently used window.
(setq window (or (window--try-to-split-window
- (get-largest-window frame t))
+ (get-largest-window frame t) alist)
(window--try-to-split-window
- (get-lru-window frame t)))))
- (prog1 (window--display-buffer buffer window
- 'window display-buffer-mark-dedicated)
+ (get-lru-window frame t) alist))))
+ (prog1 (window--display-buffer
+ buffer window 'window alist display-buffer-mark-dedicated)
(unless (cdr (assq 'inhibit-switch-frame alist))
(window--maybe-raise-frame (window-frame window)))))))
(and pop-up-windows
(display-buffer-pop-up-window buffer alist))))
-(defun display-buffer-below-selected (buffer _alist)
+(defun display-buffer-below-selected (buffer alist)
"Try displaying BUFFER in a window below the selected window.
This either splits the selected window or reuses the window below
the selected one."
(let (window)
(or (and (not (frame-parameter nil 'unsplittable))
- (setq window (window--try-to-split-window (selected-window)))
+ (setq window (window--try-to-split-window (selected-window) alist))
(window--display-buffer
- buffer window 'window display-buffer-mark-dedicated))
+ buffer window 'window alist display-buffer-mark-dedicated))
(and (setq window (window-in-direction 'below))
(not (window-dedicated-p window))
(window--display-buffer
- buffer window 'reuse display-buffer-mark-dedicated)))))
+ buffer window 'reuse alist display-buffer-mark-dedicated)))))
-(defun display-buffer-at-bottom (buffer _alist)
+(defun display-buffer-at-bottom (buffer alist)
"Try displaying BUFFER in a window at the botom of the selected frame.
This either splits the window at the bottom of the frame or the
frame's root window, or reuses an existing window at the bottom
(let (bottom-window window)
(walk-window-tree (lambda (window) (setq bottom-window window)))
(or (and (not (frame-parameter nil 'unsplittable))
- (setq window (window--try-to-split-window bottom-window))
+ (setq window (window--try-to-split-window bottom-window alist))
(window--display-buffer
- buffer window 'window display-buffer-mark-dedicated))
+ buffer window 'window alist display-buffer-mark-dedicated))
(and (not (frame-parameter nil 'unsplittable))
(setq window
(condition-case nil
(split-window (frame-root-window))
(error nil)))
(window--display-buffer
- buffer window 'window display-buffer-mark-dedicated))
+ buffer window 'window alist display-buffer-mark-dedicated))
(and (setq window bottom-window)
(not (window-dedicated-p window))
(window--display-buffer
- buffer window 'reuse display-buffer-mark-dedicated)))))
+ buffer window 'reuse alist display-buffer-mark-dedicated)))))
(defun display-buffer-in-previous-window (buffer alist)
"Display BUFFER in a window previously showing it.
(setq best-window window)))
;; Return best or second best window found.
(when (setq window (or best-window second-best-window))
- (window--display-buffer buffer window 'reuse))))
+ (window--display-buffer buffer window 'reuse alist))))
(defun display-buffer-use-some-window (buffer alist)
"Display BUFFER in an existing window.
(get-largest-window 0 not-this-window))))
(when (window-live-p window)
(prog1
- (window--display-buffer buffer window 'reuse)
+ (window--display-buffer buffer window 'reuse alist)
(window--even-window-heights window)
(unless (cdr (assq 'inhibit-switch-frame alist))
(window--maybe-raise-frame (window-frame window)))))))
window))))
;;; Resizing buffers to fit their contents exactly.
+(defcustom fit-frame-to-buffer nil
+ "Non-nil means `fit-window-to-buffer' can resize frames.
+A frame can be resized if and only if its root window is a live
+window. The height of the root window is subject to the values
+of `fit-frame-to-buffer-max-height' and `window-min-height'."
+ :type 'boolean
+ :version "24.2"
+ :group 'help)
+
+(defcustom fit-frame-to-buffer-bottom-margin 4
+ "Bottom margin for `fit-frame-to-buffer'.
+This is the number of lines `fit-frame-to-buffer' leaves free at the
+bottom of the display in order to not obscure the system task bar."
+ :type 'integer
+ :version "24.2"
+ :group 'windows)
+
+(defun fit-frame-to-buffer (&optional frame max-height min-height)
+ "Adjust height of FRAME to display its buffer's contents exactly.
+FRAME can be any live frame and defaults to the selected one.
+
+Optional argument MAX-HEIGHT specifies the maximum height of
+FRAME and defaults to the height of the display below the current
+top line of FRAME minus FIT-FRAME-TO-BUFFER-BOTTOM-MARGIN.
+Optional argument MIN-HEIGHT specifies the minimum height of
+FRAME."
+ (interactive)
+ (setq frame (window-normalize-frame frame))
+ (let* ((root (frame-root-window frame))
+ (frame-min-height
+ (+ (- (frame-height frame) (window-total-size root))
+ window-min-height))
+ (frame-top (frame-parameter frame 'top))
+ (top (if (consp frame-top)
+ (funcall (car frame-top) (cadr frame-top))
+ frame-top))
+ (frame-max-height
+ (- (/ (- (x-display-pixel-height frame) top)
+ (frame-char-height frame))
+ fit-frame-to-buffer-bottom-margin))
+ (compensate 0)
+ delta)
+ (when (and (window-live-p root) (not (window-size-fixed-p root)))
+ (with-selected-window root
+ (cond
+ ((not max-height)
+ (setq max-height frame-max-height))
+ ((numberp max-height)
+ (setq max-height (min max-height frame-max-height)))
+ (t
+ (error "%s is an invalid maximum height" max-height)))
+ (cond
+ ((not min-height)
+ (setq min-height frame-min-height))
+ ((numberp min-height)
+ (setq min-height (min min-height frame-min-height)))
+ (t
+ (error "%s is an invalid minimum height" min-height)))
+ ;; When tool-bar-mode is enabled and we have just created a new
+ ;; frame, reserve lines for toolbar resizing. This is 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.
+ (let ((quit-restore (window-parameter root 'quit-restore))
+ (lines (tool-bar-lines-needed frame)))
+ (when (and quit-restore (eq (car quit-restore) 'frame)
+ (not (zerop lines)))
+ (setq compensate (1- lines))))
+ (message "%s" compensate)
+ (setq delta
+ ;; Always count a final newline - we don't do any
+ ;; post-processing, so let's play safe.
+ (+ (count-screen-lines nil nil t)
+ (- (window-body-size))
+ compensate)))
+ ;; Move away from final newline.
+ (when (and (eobp) (bolp) (not (bobp)))
+ (set-window-point root (line-beginning-position 0)))
+ (set-window-start root (point-min))
+ (set-window-vscroll root 0)
+ (condition-case nil
+ (set-frame-height
+ frame
+ (min (max (+ (frame-height frame) delta)
+ min-height)
+ max-height))
+ (error (setq delta nil))))
+ delta))
+
(defun fit-window-to-buffer (&optional window max-height min-height)
"Adjust height of WINDOW to display its buffer's contents exactly.
WINDOW must be a live window and defaults to the selected one.
WINDOW was scrolled."
(interactive)
(setq window (window-normalize-window window t))
- ;; Can't resize a full height or fixed-size window.
- (unless (or (window-size-fixed-p window)
- (window-full-height-p window))
+ (cond
+ ((window-size-fixed-p window))
+ ((window-full-height-p window)
+ (when fit-frame-to-buffer
+ (fit-frame-to-buffer (window-frame window))))
+ (t
(with-selected-window window
(let* ((height (window-total-size))
(min-height
;; Can't get larger than height of frame.
(min max-height
(window-total-size (frame-root-window window)))
- ;, Don't delete other windows.
+ ;; Don't delete other windows.
(+ height (window-max-delta nil nil window))))
;; Make `desired-height' the height necessary to show
;; all of WINDOW's buffer, constrained by MIN-HEIGHT
(window-resize window 1 nil window)
(setq desired-height (1+ desired-height)))))
(error (setq delta nil)))
- delta))))
-
-(defcustom fit-frame-to-buffer-bottom-margin 4
- "Bottom margin for `fit-frame-to-buffer'.
-This is the number of lines `fit-frame-to-buffer' leaves free at the
-bottom of the display in order to not obscure the system task bar."
- :type 'integer
- :version "24.2"
- :group 'windows)
-
-(defun fit-frame-to-buffer (&optional frame max-height min-height)
- "Adjust height of FRAME to display its buffer's contents exactly.
-FRAME can be any live frame and defaults to the selected one.
-
-Optional argument MAX-HEIGHT specifies the maximum height of
-FRAME and defaults to the height of the display below the current
-top line of FRAME minus FIT-FRAME-TO-BUFFER-BOTTOM-MARGIN.
-Optional argument MIN-HEIGHT specifies the minimum height of
-FRAME."
- (interactive)
- (setq frame (window-normalize-frame frame))
- (let* ((root (frame-root-window frame))
- (frame-min-height
- (+ (- (frame-height frame) (window-total-size root))
- window-min-height))
- (frame-top (frame-parameter frame 'top))
- (top (if (consp frame-top)
- (funcall (car frame-top) (cadr frame-top))
- frame-top))
- (frame-max-height
- (- (/ (- (x-display-pixel-height frame) top)
- (frame-char-height frame))
- fit-frame-to-buffer-bottom-margin))
- (compensate 0)
- delta)
- (when (and (window-live-p root) (not (window-size-fixed-p root)))
- (with-selected-window root
- (cond
- ((not max-height)
- (setq max-height frame-max-height))
- ((numberp max-height)
- (setq max-height (min max-height frame-max-height)))
- (t
- (error "%s is an invalid maximum height" max-height)))
- (cond
- ((not min-height)
- (setq min-height frame-min-height))
- ((numberp min-height)
- (setq min-height (min min-height frame-min-height)))
- (t
- (error "%s is an invalid minimum height" min-height)))
- ;; When tool-bar-mode is enabled and we have just created a new
- ;; frame, reserve lines for toolbar resizing. This is 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.
- (let ((quit-restore (window-parameter root 'quit-restore))
- (lines (tool-bar-lines-needed frame)))
- (when (and quit-restore (eq (car quit-restore) 'frame)
- (not (zerop lines)))
- (setq compensate (1- lines))))
- (message "%s" compensate)
- (setq delta
- ;; Always count a final newline - we don't do any
- ;; post-processing, so let's play safe.
- (+ (count-screen-lines nil nil t)
- (- (window-body-size))
- compensate)))
- ;; Move away from final newline.
- (when (and (eobp) (bolp) (not (bobp)))
- (set-window-point root (line-beginning-position 0)))
- (set-window-start root (point-min))
- (set-window-vscroll root 0)
- (condition-case nil
- (set-frame-height
- frame
- (min (max (+ (frame-height frame) delta)
- min-height)
- max-height))
- (error (setq delta nil))))
- delta))
+ delta)))))
(defun window-safely-shrinkable-p (&optional window)
"Return t if WINDOW can be shrunk without shrinking other windows.