diff options
Diffstat (limited to 'lisp/window.el')
-rw-r--r-- | lisp/window.el | 187 |
1 files changed, 129 insertions, 58 deletions
diff --git a/lisp/window.el b/lisp/window.el index c73f019870b..a05dddeac9e 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -185,16 +185,19 @@ argument replaces this)." (let ((buffer (make-symbol "buffer")) (window (make-symbol "window")) (value (make-symbol "value"))) - `(let* ((,buffer (temp-buffer-window-setup ,buffer-or-name)) - (standard-output ,buffer) - ,window ,value) - (setq ,value (progn ,@body)) - (with-current-buffer ,buffer - (setq ,window (temp-buffer-window-show ,buffer ,action))) - - (if (functionp ,quit-function) - (funcall ,quit-function ,window ,value) - ,value)))) + (macroexp-let2 nil vbuffer-or-name buffer-or-name + (macroexp-let2 nil vaction action + (macroexp-let2 nil vquit-function quit-function + `(let* ((,buffer (temp-buffer-window-setup ,vbuffer-or-name)) + (standard-output ,buffer) + ,window ,value) + (setq ,value (progn ,@body)) + (with-current-buffer ,buffer + (setq ,window (temp-buffer-window-show ,buffer ,vaction))) + + (if (functionp ,vquit-function) + (funcall ,vquit-function ,window ,value) + ,value))))))) (defmacro with-current-buffer-window (buffer-or-name action quit-function &rest body) "Evaluate BODY with a buffer BUFFER-OR-NAME current and show that buffer. @@ -205,16 +208,50 @@ BODY." (let ((buffer (make-symbol "buffer")) (window (make-symbol "window")) (value (make-symbol "value"))) - `(let* ((,buffer (temp-buffer-window-setup ,buffer-or-name)) - (standard-output ,buffer) - ,window ,value) - (with-current-buffer ,buffer - (setq ,value (progn ,@body)) - (setq ,window (temp-buffer-window-show ,buffer ,action))) + (macroexp-let2 nil vbuffer-or-name buffer-or-name + (macroexp-let2 nil vaction action + (macroexp-let2 nil vquit-function quit-function + `(let* ((,buffer (temp-buffer-window-setup ,vbuffer-or-name)) + (standard-output ,buffer) + ,window ,value) + (with-current-buffer ,buffer + (setq ,value (progn ,@body)) + (setq ,window (temp-buffer-window-show ,buffer ,vaction))) + + (if (functionp ,vquit-function) + (funcall ,vquit-function ,window ,value) + ,value))))))) + +(defmacro with-displayed-buffer-window (buffer-or-name action quit-function &rest body) + "Show a buffer BUFFER-OR-NAME and evaluate BODY in that buffer. +This construct is like `with-current-buffer-window' but unlike that +displays the buffer specified by BUFFER-OR-NAME before running BODY." + (declare (debug t)) + (let ((buffer (make-symbol "buffer")) + (window (make-symbol "window")) + (value (make-symbol "value"))) + (macroexp-let2 nil vbuffer-or-name buffer-or-name + (macroexp-let2 nil vaction action + (macroexp-let2 nil vquit-function quit-function + `(let* ((,buffer (temp-buffer-window-setup ,vbuffer-or-name)) + (standard-output ,buffer) + ,window ,value) + (with-current-buffer ,buffer + (setq ,window (temp-buffer-window-show ,buffer ,vaction))) - (if (functionp ,quit-function) - (funcall ,quit-function ,window ,value) - ,value)))) + (let ((inhibit-read-only t) + (inhibit-modification-hooks t)) + (setq ,value (progn ,@body))) + + (set-window-point ,window (point-min)) + + (when (functionp (cdr (assq 'window-height (cdr ,vaction)))) + (ignore-errors + (funcall (cdr (assq 'window-height (cdr ,vaction))) ,window))) + + (if (functionp ,vquit-function) + (funcall ,vquit-function ,window ,value) + ,value))))))) ;; The following two functions are like `window-next-sibling' and ;; `window-prev-sibling' but the WINDOW argument is _not_ optional (so @@ -341,9 +378,9 @@ Anything less might crash Emacs.") (defcustom window-min-height 4 "The minimum total height, in lines, of any window. The value has to accommodate one text line, a mode and header -line, and a bottom divider, if present. A value less than -`window-safe-min-height' is ignored. The value of this variable -is honored when windows are resized or split. +line, a horizontal scroll bar and a bottom divider, if present. +A value less than `window-safe-min-height' is ignored. The value +of this variable is honored when windows are resized or split. Applications should never rebind this variable. To resize a window to a height less than the one specified here, an @@ -1100,11 +1137,12 @@ dumping to it." (format "frame text pixel: %s x %s cols/lines: %s x %s\n" (frame-text-width frame) (frame-text-height frame) (frame-text-cols frame) (frame-text-lines frame)) - (format "tool: %s scroll: %s fringe: %s border: %s right: %s bottom: %s\n\n" + (format "tool: %s scroll: %s/%s fringe: %s border: %s right: %s bottom: %s\n\n" (if (fboundp 'tool-bar-height) (tool-bar-height frame t) "0") (frame-scroll-bar-width frame) + (frame-scroll-bar-height frame) (frame-fringe-width frame) (frame-border-width frame) (frame-right-divider-width frame) @@ -1234,12 +1272,14 @@ of WINDOW." value) (with-current-buffer (window-buffer window) (cond + ((window-minibuffer-p window) + (if pixelwise (frame-char-height (window-frame window)) 1)) ((and (not (window--size-ignore-p window ignore)) (window-size-fixed-p window horizontal)) ;; The minimum size of a fixed size window is its size. (window-size window horizontal pixelwise)) - ((or (eq ignore 'safe) (eq ignore window)) - ;; If IGNORE equals `safe' or WINDOW return the safe values. + ((eq ignore 'safe) + ;; If IGNORE equals `safe' return the safe value. (window-safe-min-size window horizontal pixelwise)) (horizontal ;; For the minimum width of a window take fringes and @@ -1250,8 +1290,11 @@ of WINDOW." ;; `window-min-width'. (let* ((char-size (frame-char-size window t)) (fringes (window-fringes window)) + (margins (window-margins window)) (pixel-width (+ (window-safe-min-size window t t) + (* (or (car margins) 0) char-size) + (* (or (cdr margins) 0) char-size) (car fringes) (cadr fringes) (window-scroll-bar-width window) (window-right-divider-width window)))) @@ -1263,7 +1306,7 @@ of WINDOW." (* (ceiling pixel-width char-size) char-size)) (if (window--size-ignore-p window ignore) 0 - (window-min-pixel-width))) + (window-min-pixel-width window))) (max (ceiling pixel-width char-size) (if (window--size-ignore-p window ignore) @@ -1273,6 +1316,7 @@ of WINDOW." (pixel-height (+ (window-safe-min-size window nil t) (window-header-line-height window) + (window-scroll-bar-height window) (window-mode-line-height window) (window-bottom-divider-width window)))) (if pixelwise @@ -1283,7 +1327,7 @@ of WINDOW." (* (ceiling pixel-height char-size) char-size)) (if (window--size-ignore-p window ignore) 0 - (window-min-pixel-height))) + (window-min-pixel-height window))) (max (ceiling pixel-height char-size) (if (window--size-ignore-p window ignore) 0 @@ -1480,6 +1524,18 @@ by which WINDOW can be shrunk." (window--min-delta-1 window (- size minimum) horizontal ignore trail noup pixelwise))))) +(defun frame-windows-min-size (&optional frame horizontal pixelwise) + "Return minimum number of lines of FRAME's windows. +HORIZONTAL non-nil means return number of columns of FRAME's +windows. PIXELWISE non-nil means return sizes in pixels." + (setq frame (window-normalize-frame frame)) + (let* ((root (frame-root-window frame)) + (mini (window-next-sibling root))) + (+ (window-min-size root horizontal nil pixelwise) + (if (and mini (not horizontal)) + (window-min-size mini horizontal nil pixelwise) + 0)))) + (defun window--max-delta-1 (window delta &optional horizontal ignore trail noup pixelwise) "Internal function of `window-max-delta'." (if (not (window-parent window)) @@ -2956,6 +3012,28 @@ routines." pixel-delta (/ pixel-delta (frame-char-height frame))))) +(defun window--sanitize-window-sizes (frame horizontal) + "Assert that all windows on FRAME are large enough. +If necessary and possible, make sure that every window on frame +FRAME has its minimum height. Optional argument HORIZONTAL +non-nil means to make sure that every window on frame FRAME has +its minimum width. The minimumm height/width of a window is the +respective value returned by `window-min-size' for that window. + +Return t if all windows were resized appropriately. Return nil +if at least one window could not be resized as requested, which +may happen when the FRAME is not large enough to accomodate it." + (let ((value t)) + (walk-window-tree + (lambda (window) + (let ((delta (- (window-min-size window horizontal nil t) + (window-size window horizontal t)))) + (when (> delta 0) + (if (window-resizable-p window delta horizontal nil t) + (window-resize window delta horizontal nil t) + (setq value nil)))))) + value)) + (defun adjust-window-trailing-edge (window delta &optional horizontal pixelwise) "Move WINDOW's bottom edge by DELTA lines. Optional argument HORIZONTAL non-nil means move WINDOW's right @@ -4213,20 +4291,6 @@ showing BUFFER-OR-NAME." ;; If a window doesn't show BUFFER, unrecord BUFFER in it. (unrecord-window-buffer window buffer))))) -;;; Splitting windows. -(defun window-split-min-size (&optional horizontal pixelwise) - "Return minimum height of any window when splitting windows. -Optional argument HORIZONTAL non-nil means return minimum width." - (cond - (pixelwise - (if horizontal - (window-min-pixel-width) - (window-min-pixel-height))) - (horizontal - (max window-min-width window-safe-min-width)) - (t - (max window-min-height window-safe-min-height)))) - (defun split-window (&optional window size side pixelwise) "Make a new window adjacent to WINDOW. WINDOW must be a valid window and defaults to the selected one. @@ -4290,6 +4354,9 @@ frame. The selected window is not changed by this function." (pixel-size (when (numberp size) (window--size-to-pixel window size horizontal pixelwise t))) + (divider-width (if horizontal + (frame-right-divider-width frame) + (frame-bottom-divider-width frame))) atom-root) (window--check frame) (catch 'done @@ -4391,19 +4458,14 @@ frame. The selected window is not changed by this function." (cond (resize ;; SIZE unspecified, resizing. - (when (and (not (window-sizable-p - parent (- new-pixel-size) horizontal nil t)) - ;; Try again with minimum split size. - (setq new-pixel-size - (max new-pixel-size - (window-split-min-size horizontal t))) - (not (window-sizable-p - parent (- new-pixel-size) horizontal nil t))) - (error "Window %s too small for splitting 1" parent))) - ((> (+ new-pixel-size (window-min-size window horizontal nil t)) + (unless (window-sizable-p + parent (- new-pixel-size divider-width) horizontal nil t) + (error "Window %s too small for splitting (1)" parent))) + ((> (+ new-pixel-size divider-width + (window-min-size window horizontal nil t)) old-pixel-size) ;; SIZE unspecified, no resizing. - (error "Window %s too small for splitting 2" window)))) + (error "Window %s too small for splitting (2)" window)))) ((and (>= pixel-size 0) (or (>= pixel-size old-pixel-size) (< new-pixel-size @@ -4411,19 +4473,19 @@ frame. The selected window is not changed by this function." ;; SIZE specified as new size of old window. If the new size ;; is larger than the old size or the size of the new window ;; would be less than the safe minimum, signal an error. - (error "Window %s too small for splitting 3" window)) + (error "Window %s too small for splitting (3)" window)) (resize ;; SIZE specified, resizing. (unless (window-sizable-p - parent (- new-pixel-size) horizontal nil t) + parent (- new-pixel-size divider-width) horizontal nil t) ;; If we cannot resize the parent give up. - (error "Window %s too small for splitting 4" parent))) + (error "Window %s too small for splitting (4)" parent))) ((or (< new-pixel-size (window-safe-min-pixel-size window horizontal)) (< (- old-pixel-size new-pixel-size) (window-safe-min-pixel-size window horizontal))) ;; SIZE specification violates minimum size restrictions. - (error "Window %s too small for splitting 5" window))) + (error "Window %s too small for splitting (5)" window))) (window--resize-reset frame horizontal) @@ -4494,6 +4556,9 @@ frame. The selected window is not changed by this function." (set-window-parameter (window-parent new) 'window-atom t)) (set-window-parameter new 'window-atom t))) + ;; Sanitize sizes. + (window--sanitize-window-sizes frame horizontal) + (run-window-configuration-change-hook frame) (run-window-scroll-functions new) (window--check frame) @@ -5065,7 +5130,7 @@ value can be also stored on disk and read back in a new session." (let ((scroll-bars (cdr (assq 'scroll-bars state)))) (set-window-scroll-bars window (car scroll-bars) (nth 2 scroll-bars) - (nth 3 scroll-bars))) + (or (nth 3 scroll-bars) 0) (nth 5 scroll-bars))) (set-window-vscroll window (cdr (assq 'vscroll state))) ;; Adjust vertically. (if (memq window-size-fixed '(t height)) @@ -5989,6 +6054,8 @@ The actual non-nil value of this variable will be copied to the (const display-buffer-pop-up-window) (const display-buffer-same-window) (const display-buffer-pop-up-frame) + (const display-buffer-below-selected) + (const display-buffer-at-bottom) (const display-buffer-in-previous-window) (const display-buffer-use-some-window) (function :tag "Other function")) @@ -7089,7 +7156,10 @@ FRAME." (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)))) + (height + (+ (cdr value) + (window-bottom-divider-width) + (nth 3 (window-scroll-bars))))) ;; Don't change height or width when the window's size is fixed ;; in either direction or ONLY forbids it. (cond @@ -7248,6 +7318,7 @@ accessible position." ;; height. Its width remains fixed. (setq height (+ (cdr (window-text-pixel-size nil nil t nil (frame-pixel-height) t)) + (nth 3 (window-scroll-bars window)) (window-bottom-divider-width))) ;; Round height. (unless pixelwise |