X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/389698e53a4d3130035e46bf7f8b28480ae9ed8a..833f9821f534730423a7757ce3d302314af29d63:/lisp/window.el?ds=sidebyside diff --git a/lisp/window.el b/lisp/window.el index 46a7dd0827..d9c0d0afbe 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -1835,6 +1835,8 @@ optional argument PIXELWISE is passed to the functions." (window-body-width window pixelwise) (window-body-height window pixelwise))) +(declare-function font-info "font.c" (name &optional frame)) + (defun window-font-width (&optional window face) "Return average character width for the font of FACE used in WINDOW. WINDOW must be a live window and defaults to the selected one. @@ -1866,6 +1868,8 @@ information for the remapped face." (aref info 3)) (frame-char-height)))) +(defvar overflow-newline-into-fringe) + (defun window-max-chars-per-line (&optional window face) "Return the number of characters that can be displayed on one line in WINDOW. WINDOW must be a live window and defaults to the selected one. @@ -3870,12 +3874,10 @@ before was current this also makes BUFFER the current buffer." (defcustom switch-to-visible-buffer t "If non-nil, allow switching to an already visible buffer. If this variable is non-nil, `switch-to-prev-buffer' and -`switch-to-next-buffer' may switch to an already visible buffer -provided the buffer was shown before in the window specified as -argument to those functions. If this variable is nil, -`switch-to-prev-buffer' and `switch-to-next-buffer' always try to -avoid switching to a buffer that is already visible in another -window on the same frame." +`switch-to-next-buffer' may switch to an already visible buffer. +If this variable is nil, `switch-to-prev-buffer' and +`switch-to-next-buffer' always try to avoid switching to a buffer +that is already visible in another window on the same frame." :type 'boolean :version "24.1" :group 'windows) @@ -3946,7 +3948,8 @@ to it." (or (null pred) (funcall pred buffer)) (not (eq (aref (buffer-name buffer) 0) ?\s)) (or bury-or-kill (not (memq buffer next-buffers)))) - (if (get-buffer-window buffer frame) + (if (and (not switch-to-visible-buffer) + (get-buffer-window buffer frame)) ;; Try to avoid showing a buffer visible in some other window. (unless visible (setq visible buffer)) @@ -4048,7 +4051,8 @@ found." (or (null pred) (funcall pred buffer)) (not (eq (aref (buffer-name buffer) 0) ?\s)) (not (assq buffer (window-prev-buffers window)))) - (if (get-buffer-window buffer frame) + (if (and (not switch-to-visible-buffer) + (get-buffer-window buffer frame)) ;; Try to avoid showing a buffer visible in some other window. (setq visible buffer) (setq new-buffer buffer) @@ -4307,7 +4311,7 @@ one. If non-nil, reset `quit-restore' parameter to nil. Optional second argument BURY-OR-KILL tells how to proceed with the buffer of WINDOW. The following values are handled: -`nil' means to not handle the buffer in a particular way. This +nil means to not handle the buffer in a particular way. This means that if WINDOW is not deleted by this function, invoking `switch-to-prev-buffer' will usually show the buffer again. @@ -4354,11 +4358,18 @@ the buffer of WINDOW. The following values are handled: (eq (nth 3 quit-restore) buffer)) ;; Show another buffer stored in quit-restore parameter. (when (and (integerp (nth 3 quad)) - (/= (nth 3 quad) (window-total-height window))) + (if (window-combined-p window) + (/= (nth 3 quad) (window-total-height window)) + (/= (nth 3 quad) (window-total-width window)))) ;; Try to resize WINDOW to its old height but don't signal an ;; error. (condition-case nil - (window-resize window (- (nth 3 quad) (window-total-height window))) + (window-resize + window + (- (nth 3 quad) (if (window-combined-p window) + (window-total-height window) + (window-total-width window))) + (window-combined-p window t)) (error nil))) (set-window-dedicated-p window nil) ;; Restore WINDOW's previous buffer, start and point position. @@ -5371,6 +5382,8 @@ windows can get as small as `window-safe-min-height' and root)))) (delete-other-windows-internal window root))) + (set-window-dedicated-p window nil) + (let* ((frame (window-frame window)) (head (car state)) ;; We check here (1) whether the total sizes of root window of @@ -5474,10 +5487,16 @@ element is BUFFER." (cond ((eq type 'reuse) (if (eq (window-buffer window) buffer) - ;; WINDOW shows BUFFER already. - (when (consp (window-parameter window 'quit-restore)) - ;; If WINDOW has a quit-restore parameter, reset its car. - (setcar (window-parameter window 'quit-restore) 'same)) + ;; WINDOW shows BUFFER already. Update WINDOW's quit-restore + ;; parameter, if any. + (let ((quit-restore (window-parameter window 'quit-restore))) + (when (consp quit-restore) + (setcar quit-restore 'same) + ;; The selected-window might have changed in + ;; between (Bug#20353). + (unless (or (eq window (selected-window)) + (eq window (nth 2 quit-restore))) + (setcar (cddr quit-restore) (selected-window))))) ;; WINDOW shows another buffer. (with-current-buffer (window-buffer window) (set-window-parameter @@ -5488,7 +5507,9 @@ element is BUFFER." ;; Preserve window-point-insertion-type (Bug#12588). (copy-marker (window-point window) window-point-insertion-type) - (window-total-height window)) + (if (window-combined-p window) + (window-total-height window) + (window-total-width window))) (selected-window) buffer))))) ((eq type 'window) ;; WINDOW has been created on an existing frame. @@ -6069,33 +6090,43 @@ represents a live window, nil otherwise." )) frame)))) -(defcustom even-window-heights t - "If non-nil `display-buffer' will try to even window heights. +(defcustom even-window-sizes t + "If non-nil `display-buffer' will try to even window sizes. Otherwise `display-buffer' will leave the window configuration -alone. Heights are evened only when `display-buffer' chooses a -window that appears above or below the selected window." - :type 'boolean +alone. Special values are `height-only' to even heights only and +`width-only' to even widths only. Any other value means to even +any of them." + :type '(choice + (const :tag "Never" nil) + (const :tag "Side-by-side windows only" width-only) + (const :tag "Windows above or below only" height-only) + (const :tag "Always" t)) + :version "25.1" :group 'windows) - -(defun window--even-window-heights (window) - "Even heights of WINDOW and selected window. -Do this only if these windows are vertically adjacent to each -other, `even-window-heights' is non-nil, and the selected window -is higher than WINDOW." - (when (and even-window-heights - ;; Even iff WINDOW forms a vertical combination with the - ;; selected window, and WINDOW's height exceeds that of the - ;; selected window, see also bug#11880. - (window-combined-p window) - (= (window-child-count (window-parent window)) 2) - (eq (window-parent) (window-parent window)) - (> (window-total-height) (window-total-height window))) - ;; Don't throw an error if we can't even window heights for - ;; whatever reason. - (condition-case nil - (enlarge-window - (/ (- (window-total-height window) (window-total-height)) 2)) - (error nil)))) +(defvaralias 'even-window-heights 'even-window-sizes) + +(defun window--even-window-sizes (window) + "Even sizes of WINDOW and selected window. +Even only if these windows are the only children of their parent, +`even-window-sizes' has the appropriate value and the selected +window is larger than WINDOW." + (when (and (= (window-child-count (window-parent window)) 2) + (eq (window-parent) (window-parent window))) + (cond + ((and (not (memq even-window-sizes '(nil height-only))) + (window-combined-p window t) + (> (window-total-width) (window-total-width window))) + (condition-case nil + (enlarge-window + (/ (- (window-total-width window) (window-total-width)) 2) t) + (error nil))) + ((and (not (memq even-window-sizes '(nil width-only))) + (window-combined-p window) + (> (window-total-height) (window-total-height window))) + (condition-case nil + (enlarge-window + (/ (- (window-total-height window) (window-total-height)) 2)) + (error nil)))))) (defun window--display-buffer (buffer window type &optional alist dedicated) "Display BUFFER in WINDOW. @@ -6213,6 +6244,7 @@ The actual non-nil value of this variable will be copied to the (const display-buffer-at-bottom) (const display-buffer-in-previous-window) (const display-buffer-use-some-window) + (const display-buffer-use-some-frame) (function :tag "Other function")) "Custom type for `display-buffer' action functions.") @@ -6357,6 +6389,7 @@ Available action functions include: `display-buffer-pop-up-window' `display-buffer-in-previous-window' `display-buffer-use-some-window' + `display-buffer-use-some-frame' Recognized alist entries include: @@ -6457,6 +6490,41 @@ its documentation for additional customization information." ;;; `display-buffer' action functions: +(defun display-buffer-use-some-frame (buffer alist) + "Display BUFFER in an existing frame that meets a predicate +\(by default any frame other than the current frame). If +successful, return the window used; otherwise return nil. + +If ALIST has a non-nil `inhibit-switch-frame' entry, avoid +raising the frame. + +If ALIST has a non-nil `frame-predicate' entry, its value is a +function taking one argument (a frame), returning non-nil if the +frame is a candidate; this function replaces the default +predicate. + +If ALIST has a non-nil `inhibit-same-window' entry, avoid using +the currently selected window (only useful with a frame-predicate +that allows the selected frame)." + (let* ((predicate (or (cdr (assq 'frame-predicate alist)) + (lambda (frame) + (and + (not (eq frame (selected-frame))) + (not (window-dedicated-p + (or + (get-lru-window frame) + (frame-first-window frame))))) + ))) + (frame (car (filtered-frame-list predicate))) + (window (and frame (get-lru-window frame nil (cdr (assq 'inhibit-same-window alist)))))) + (when window + (prog1 + (window--display-buffer + buffer window 'frame alist display-buffer-mark-dedicated) + (unless (cdr (assq 'inhibit-switch-frame alist)) + (window--maybe-raise-frame frame)))) + )) + (defun display-buffer-same-window (buffer alist) "Display BUFFER in the selected window. This fails if ALIST has a non-nil `inhibit-same-window' entry, or @@ -6755,7 +6823,7 @@ that frame." (prog1 (window--display-buffer buffer window 'reuse alist) - (window--even-window-heights window) + (window--even-window-sizes window) (unless (cdr (assq 'inhibit-switch-frame alist)) (window--maybe-raise-frame (window-frame window))))))) @@ -6874,6 +6942,33 @@ the selected window or never appeared in it before, or if :group 'windows :version "24.3") +(defcustom switch-to-buffer-in-dedicated-window nil + "Allow switching to buffer in strongly dedicated windows. +If non-nil, allow `switch-to-buffer' to proceed when called +interactively and the selected window is strongly dedicated to +its buffer. + +The following values are recognized: + +nil - disallow switching; signal an error + +prompt - prompt user whether to allow switching + +pop - perform `pop-to-buffer' instead + +t - undedicate selected window and switch + +When called non-interactively, `switch-to-buffer' always signals +an error when the selected window is dedicated to its buffer and +FORCE-SAME-WINDOW is non-nil." + :type '(choice + (const :tag "Disallow" nil) + (const :tag "Prompt" prompt) + (const :tag "Pop" pop) + (const :tag "Allow" t)) + :group 'windows + :version "25.1") + (defun switch-to-buffer (buffer-or-name &optional norecord force-same-window) "Display buffer BUFFER-OR-NAME in the selected window. @@ -6881,10 +6976,12 @@ WARNING: This is NOT the way to work on another buffer temporarily within a Lisp program! Use `set-buffer' instead. That avoids messing with the window-buffer correspondences. -If the selected window cannot display the specified -buffer (e.g. if it is a minibuffer window or strongly dedicated -to another buffer), call `pop-to-buffer' to select the buffer in -another window. +If the selected window cannot display the specified buffer +because it is a minibuffer window or strongly dedicated to +another buffer, call `pop-to-buffer' to select the buffer in +another window. In interactive use, if the selected window is +strongly dedicated to its buffer, the value of the option +`switch-to-buffer-in-dedicated-window' specifies how to proceed. If called interactively, read the buffer name using the minibuffer. The variable `confirm-nonexistent-file-or-buffer' @@ -6901,8 +6998,9 @@ at the front of the buffer list, and do not make the window displaying it the most recently selected one. If optional argument FORCE-SAME-WINDOW is non-nil, the buffer -must be displayed in the selected window; if that is impossible, -signal an error rather than calling `pop-to-buffer'. +must be displayed in the selected window when called +non-interactively; if that is impossible, signal an error rather +than calling `pop-to-buffer'. The option `switch-to-buffer-preserve-window-point' can be used to make the buffer appear at its last position in the selected @@ -6910,7 +7008,25 @@ window. Return the buffer switched to." (interactive - (list (read-buffer-to-switch "Switch to buffer: ") nil 'force-same-window)) + (let ((force-same-window + (cond + ((window-minibuffer-p) nil) + ((not (eq (window-dedicated-p) t)) 'force-same-window) + ((pcase switch-to-buffer-in-dedicated-window + (`nil (user-error + "Cannot switch buffers in a dedicated window")) + (`prompt + (if (y-or-n-p + (format "Window is dedicated to %s; undedicate it" + (window-buffer))) + (progn + (set-window-dedicated-p nil nil) + 'force-same-window) + (user-error + "Cannot switch buffers in a dedicated window"))) + (`pop nil) + (_ (set-window-dedicated-p nil nil) 'force-same-window)))))) + (list (read-buffer-to-switch "Switch to buffer: ") nil force-same-window))) (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name))) (cond ;; Don't call set-window-buffer if it's not needed since it @@ -7181,6 +7297,8 @@ See also `fit-frame-to-buffer-margins'." (<= left (- right margin)) (<= margin right)) margin)) +(declare-function tool-bar-height "xdisp.c" (&optional frame pixelwise)) + (defun fit-frame-to-buffer (&optional frame max-height min-height max-width min-width only) "Adjust size of FRAME to display the contents of its buffer exactly. FRAME can be any live frame and defaults to the selected one. @@ -7619,7 +7737,8 @@ Return non-nil if the window was shrunk, nil otherwise." (defvar recenter-last-op nil "Indicates the last recenter operation performed. -Possible values: `top', `middle', `bottom', integer or float numbers.") +Possible values: `top', `middle', `bottom', integer or float numbers. +It can also be nil, which means the first value in `recenter-positions'.") (defcustom recenter-positions '(middle top bottom) "Cycling order for `recenter-top-bottom'. @@ -8046,7 +8165,7 @@ This function is responsible for combining the sizes of the displayed windows and returning a cons (WIDTH . HEIGHT) describing the width and height with which Emacs will call `set-process-window-size' for that process. If the function -returns `nil', Emacs does not call `set-process-window-size'. +returns nil, Emacs does not call `set-process-window-size'. This function is called with the process buffer as the current buffer and with two arguments: the process and a list of windows