diff options
Diffstat (limited to 'lisp/window.el')
-rw-r--r-- | lisp/window.el | 461 |
1 files changed, 296 insertions, 165 deletions
diff --git a/lisp/window.el b/lisp/window.el index 2d0a73b426d..e14d472cf3f 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -2499,14 +2499,16 @@ and no others." (defalias 'some-window 'get-window-with-predicate) -(defun get-lru-window (&optional all-frames dedicated not-selected) +(defun get-lru-window (&optional all-frames dedicated not-selected no-other) "Return the least recently used window on frames specified by ALL-FRAMES. Return a full-width window if possible. A minibuffer window is never a candidate. A dedicated window is never a candidate unless DEDICATED is non-nil, so if all windows are dedicated, the value is nil. Avoid returning the selected window if possible. Optional argument NOT-SELECTED non-nil means never return the -selected window. +selected window. Optional argument NO-OTHER non-nil means to +never return a window whose 'no-other-window' parameter is +non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2526,7 +2528,9 @@ selected frame and no others." (let (best-window best-time second-best-window second-best-time time) (dolist (window (window-list-1 nil 'nomini all-frames)) (when (and (or dedicated (not (window-dedicated-p window))) - (or (not not-selected) (not (eq window (selected-window))))) + (or (not not-selected) (not (eq window (selected-window)))) + (or (not no-other) + (not (window-parameter window 'no-other-window)))) (setq time (window-use-time window)) (if (or (eq window (selected-window)) (not (window-full-width-p window))) @@ -2538,12 +2542,14 @@ selected frame and no others." (setq best-window window))))) (or best-window second-best-window))) -(defun get-mru-window (&optional all-frames dedicated not-selected) +(defun get-mru-window (&optional all-frames dedicated not-selected no-other) "Return the most recently used window on frames specified by ALL-FRAMES. A minibuffer window is never a candidate. A dedicated window is never a candidate unless DEDICATED is non-nil, so if all windows are dedicated, the value is nil. Optional argument NOT-SELECTED -non-nil means never return the selected window. +non-nil means never return the selected window. Optional +argument NO-OTHER non-nil means to never return a window whose +'no-other-window' parameter is non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2565,17 +2571,21 @@ selected frame and no others." (setq time (window-use-time window)) (when (and (or dedicated (not (window-dedicated-p window))) (or (not not-selected) (not (eq window (selected-window)))) - (or (not best-time) (> time best-time))) + (or (not no-other) + (not (window-parameter window 'no-other-window))) + (or (not best-time) (> time best-time))) (setq best-time time) (setq best-window window))) best-window)) -(defun get-largest-window (&optional all-frames dedicated not-selected) +(defun get-largest-window (&optional all-frames dedicated not-selected no-other) "Return the largest window on frames specified by ALL-FRAMES. A minibuffer window is never a candidate. A dedicated window is never a candidate unless DEDICATED is non-nil, so if all windows are dedicated, the value is nil. Optional argument NOT-SELECTED -non-nil means never return the selected window. +non-nil means never return the selected window. Optional +argument NO-OTHER non-nil means to never return a window whose +'no-other-window' parameter is non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2596,7 +2606,9 @@ selected frame and no others." best-window size) (dolist (window (window-list-1 nil 'nomini all-frames)) (when (and (or dedicated (not (window-dedicated-p window))) - (or (not not-selected) (not (eq window (selected-window))))) + (or (not not-selected) (not (eq window (selected-window)))) + (or (not no-other) + (not (window-parameter window 'no-other-window)))) (setq size (* (window-pixel-height window) (window-pixel-width window))) (when (> size best-size) @@ -3755,8 +3767,6 @@ WINDOW must be a valid window and defaults to the selected one. If the option `window-resize-pixelwise' is non-nil minimize WINDOW pixelwise." (interactive) - (when switch-to-buffer-preserve-window-point - (window--before-delete-windows window)) (setq window (window-normalize-window window)) (window-resize window @@ -4119,7 +4129,7 @@ frame can be safely deleted." (let ((minibuf (active-minibuffer-window))) (and minibuf (eq frame (window-frame minibuf)) (not (eq (default-toplevel-value - minibuffer-follows-selected-frame) + 'minibuffer-follows-selected-frame) t))))) 'frame)) ((window-minibuffer-p window) @@ -4132,53 +4142,56 @@ frame can be safely deleted." ;; of its frame. t)))) -(defun window--in-subtree-p (window root) - "Return t if WINDOW is either ROOT or a member of ROOT's subtree." - (or (eq window root) - (let ((parent (window-parent window))) - (catch 'done - (while parent - (if (eq parent root) - (throw 'done t) - (setq parent (window-parent parent)))))))) - -;; This function is called by `delete-window' and -;; `delete-other-windows' when `switch-to-buffer-preserve-window-point' -;; evaluates non-nil: it allows `winner-undo' to restore the -;; buffer point from deleted windows (Bug#23621). -(defun window--before-delete-windows (&optional window) - "Update `window-prev-buffers' before delete a window. -Optional arg WINDOW, if non-nil, update WINDOW-START and POS -in `window-prev-buffers' for all windows displaying same -buffer as WINDOW. Otherwise, update `window-prev-buffers' for -all windows. - -The new values for WINDOW-START and POS are those -returned by `window-start' and `window-point' respectively. - -This function is called only if `switch-to-buffer-preserve-window-point' -evaluates non-nil." - (dolist (win (window-list)) - (let* ((buf (window-buffer (or window win))) - (start (window-start win)) - (pos (window-point win)) - (entry (assq buf (window-prev-buffers win)))) - (cond (entry - (let ((marker (nth 2 entry))) - (unless (= pos marker) - (set-marker (nth 1 entry) start buf) - (set-marker marker pos buf)))) - (t - (let ((prev-buf (window-prev-buffers win)) - (start-m (make-marker)) - (pos-m (make-marker))) - (set-marker start-m start buf) - (set-marker pos-m pos buf) - (push (list buf start-m pos-m) prev-buf) - (set-window-prev-buffers win prev-buf))))))) +(defun window-at-x-y (x y &optional frame no-other) + "Return live window at coordinates X, Y on specified FRAME. +X and Y are FRAME-relative pixel coordinates. A coordinate on an +edge shared by two windows is attributed to the window on the +right (or below). Return nil if no such window can be found. + +Optional argument FRAME must specify a live frame and defaults to +the selected one. Optional argument NO-OTHER non-nil means to +return nil if the window located at the specified coordinates has +a non-nil `no-other-window' parameter." + (setq frame (window-normalize-frame frame)) + (let* ((root-edges (window-edges (frame-root-window frame) nil nil t)) + (root-left (nth 2 root-edges)) + (root-bottom (nth 3 root-edges))) + (catch 'window + (walk-window-tree + (lambda (window) + (let ((edges (window-edges window nil nil t))) + (when (and (>= x (nth 0 edges)) + (or (< x (nth 2 edges)) (= x root-left)) + (>= y (nth 1 edges)) + (or (< y (nth 3 edges)) (= y root-bottom))) + (if (and no-other (window-parameter window 'no-other-window)) + (throw 'window nil) + (throw 'window window))))) + frame)))) + +(defcustom delete-window-choose-selected 'mru + "How to choose a frame's selected window after window deletion. +When a frame's selected window gets deleted, Emacs has to choose +another live window on that frame to serve as its selected +window. This option allows to control which window gets selected +instead. + +The possible choices are 'mru' (the default) to select the most +recently used window on that frame, and 'pos' to choose the +window at the frame coordinates of point of the previously +selected window. If this is nil, choose the frame's first window +instead. A window with a non-nil `no-other-window' parameter is +chosen only if all windows on that frame have that parameter set +to a non-nil value." + :type '(choice (const :tag "Most recently used" mru) + (const :tag "At position of deleted" pos) + (const :tag "Frame's first " nil)) + :group 'windows + :group 'frames + :version "28.1") (defun delete-window (&optional window) - "Delete WINDOW. + "Delete specified WINDOW. WINDOW must be a valid window and defaults to the selected one. Return nil. @@ -4193,10 +4206,12 @@ Otherwise, if WINDOW is part of an atomic window, call `delete-window' with the root of the atomic window as its argument. Signal an error if WINDOW is either the only window on its frame, the last non-side window, or part of an atomic window -that is its frame's root window." +that is its frame's root window. + +If WINDOW is the selected window on its frame, choose some other +window as that frame's selected window according to the value of +the option `delete-window-choose-selected'." (interactive) - (when switch-to-buffer-preserve-window-point - (window--before-delete-windows)) (setq window (window-normalize-window window)) (let* ((frame (window-frame window)) (function (window-parameter window 'delete-window)) @@ -4230,11 +4245,11 @@ that is its frame's root window." (window-combination-resize (or window-combination-resize (window-parameter parent 'window-side))) - (frame-selected - (window--in-subtree-p (frame-selected-window frame) window)) + (frame-selected-window (frame-selected-window frame)) ;; Emacs 23 preferably gives WINDOW's space to its left ;; sibling. - (sibling (or (window-left window) (window-right window)))) + (sibling (or (window-left window) (window-right window))) + frame-selected-window-edges frame-selected-window-pos) (window--resize-reset frame horizontal) (cond ((and (not (eq window-combination-resize t)) @@ -4250,15 +4265,63 @@ that is its frame's root window." (t ;; Can't do without resizing fixed-size windows. (window--resize-siblings window (- size) horizontal t))) + + (when (eq delete-window-choose-selected 'pos) + ;; Remember edges and position of point of the selected window + ;; of WINDOW'S frame. + (setq frame-selected-window-edges + (window-edges frame-selected-window nil nil t)) + (setq frame-selected-window-pos + (nth 2 (posn-at-point nil frame-selected-window)))) + ;; Actually delete WINDOW. (delete-window-internal window) (window--pixel-to-total frame horizontal) - (when (and frame-selected - (window-parameter - (frame-selected-window frame) 'no-other-window)) - ;; `delete-window-internal' has selected a window that should - ;; not be selected, fix this here. - (other-window -1 frame)) + + ;; If we deleted the selected window of WINDOW's frame, choose + ;; another one based on `delete-window-choose-selected'. Note + ;; that both `window-at-x-y' and `get-mru-window' may fail to + ;; produce a suitable window in which case we will fall back on + ;; its frame's first window, chosen by `delete-window-internal'. + (cond + ((window-live-p frame-selected-window)) + ((and frame-selected-window-pos + ;; We have a recorded position of point of the previously + ;; selected window. Try to find the window that is now + ;; at that position. + (let ((new-frame-selected-window + (window-at-x-y + (+ (nth 0 frame-selected-window-edges) + (car frame-selected-window-pos)) + (+ (nth 1 frame-selected-window-edges) + (cdr frame-selected-window-pos)) + frame t))) + (and new-frame-selected-window + ;; Select window at WINDOW's position at point. + (set-frame-selected-window + frame new-frame-selected-window))))) + ((and (eq delete-window-choose-selected 'mru) + ;; Try to use the most recently used window. + (let ((mru-window (get-mru-window frame nil nil t))) + (and mru-window + (set-frame-selected-window frame mru-window))))) + ((and (window-parameter + (frame-selected-window frame) 'no-other-window) + ;; If `delete-window-internal' selected a window with a + ;; non-nil 'no-other-window' parameter as its frame's + ;; selected window, try to choose another one. + (catch 'found + (walk-window-tree + (lambda (other) + (unless (window-parameter other 'no-other-window) + (set-frame-selected-window frame other) + (throw 'found t))) + frame)))) + (t + ;; Record the window chosen by `delete-window-internal'. + (set-frame-selected-window + frame (frame-selected-window frame)))) + (window--check frame) ;; Always return nil. nil)))) @@ -4400,42 +4463,45 @@ This may be a useful alternative binding for \\[delete-other-windows] ;; The following function is called by `set-window-buffer' _before_ it ;; replaces the buffer of the argument window with the new buffer. +(defun push-window-buffer-onto-prev (&optional window) + "Push entry for WINDOW's buffer onto WINDOW's prev-buffers list. +WINDOW must be a live window and defaults to the selected one. + +Any duplicate entries for the buffer in the list are removed." + (let* ((window (window-normalize-window window t)) + (buffer (window-buffer window)) + (w-list (window-prev-buffers window)) + (entry (assq buffer w-list))) + (when entry + (setq w-list (assq-delete-all buffer w-list))) + (let ((start (window-start window)) + (point (window-point window))) + (setq entry + (cons buffer + (with-current-buffer buffer + (if entry + ;; We have an entry, update marker positions. + (list (set-marker (nth 1 entry) start) + (set-marker (nth 2 entry) point)) + (list (copy-marker start) + (copy-marker + ;; Preserve window-point-insertion-type + ;; (Bug#12855) + point window-point-insertion-type)))))) + (set-window-prev-buffers window (cons entry w-list))))) + (defun record-window-buffer (&optional window) "Record WINDOW's buffer. WINDOW must be a live window and defaults to the selected one." (let* ((window (window-normalize-window window t)) - (buffer (window-buffer window)) - (entry (assq buffer (window-prev-buffers window)))) + (buffer (window-buffer window))) ;; Reset WINDOW's next buffers. If needed, they are resurrected by ;; `switch-to-prev-buffer' and `switch-to-next-buffer'. (set-window-next-buffers window nil) - (when entry - ;; Remove all entries for BUFFER from WINDOW's previous buffers. - (set-window-prev-buffers - window (assq-delete-all buffer (window-prev-buffers window)))) - ;; Don't record insignificant buffers. - (unless (eq (aref (buffer-name buffer) 0) ?\s) - ;; Add an entry for buffer to WINDOW's previous buffers. - (with-current-buffer buffer - (let ((start (window-start window)) - (point (window-point window))) - (setq entry - (cons buffer - (if entry - ;; We have an entry, update marker positions. - (list (set-marker (nth 1 entry) start) - (set-marker (nth 2 entry) point)) - ;; Make new markers. - (list (copy-marker start) - (copy-marker - ;; Preserve window-point-insertion-type - ;; (Bug#12855). - point window-point-insertion-type))))) - (set-window-prev-buffers - window (cons entry (window-prev-buffers window))))) - + (when (not (eq (aref (buffer-name buffer) 0) ?\s)) + (push-window-buffer-onto-prev window) (run-hooks 'buffer-list-update-hook)))) (defun unrecord-window-buffer (&optional window buffer) @@ -4460,8 +4526,10 @@ point to POINT. If WINDOW is selected this also sets BUFFER's before was current this also makes BUFFER the current buffer." (setq window (window-normalize-window window t)) (let ((selected (eq window (selected-window))) - (current (eq (window-buffer window) (current-buffer)))) + (current (eq (window-buffer window) (current-buffer))) + (dedicated-side (eq (window-dedicated-p window) 'side))) (set-window-buffer window buffer) + (and dedicated-side (set-window-dedicated-p window 'side)) (when (and selected current) (set-buffer buffer)) (when start @@ -4595,11 +4663,11 @@ This function is called by `prev-buffer'." ;; Scan WINDOW's previous buffers first, skipping entries of next ;; buffers. (dolist (entry (window-prev-buffers window)) - (when (and (setq new-buffer (car entry)) + (when (and (not (eq (car entry) old-buffer)) + (setq new-buffer (car entry)) (or (buffer-live-p new-buffer) (not (setq killed-buffers (cons new-buffer killed-buffers)))) - (not (eq new-buffer old-buffer)) (or (null pred) (funcall pred new-buffer)) ;; When BURY-OR-KILL is nil, avoid switching to a ;; buffer in WINDOW's next buffers list. @@ -4653,8 +4721,8 @@ This function is called by `prev-buffer'." window new-buffer (nth 1 entry) (nth 2 entry)) (throw 'found t))))) - (when skipped - ;; Show first skipped buffer. + (when (and skipped (not (functionp switch-to-prev-buffer-skip))) + ;; Show first skipped buffer, unless skip was a function. (setq new-buffer skipped) (set-window-buffer-start-and-point window new-buffer))) @@ -4762,11 +4830,12 @@ This function is called by `next-buffer'." ;; Scan WINDOW's reverted previous buffers last (must not use ;; nreverse here!) (dolist (entry (reverse (window-prev-buffers window))) - (when (and (setq new-buffer (car entry)) + (when (and (not (eq new-buffer (car entry))) + (not (eq old-buffer (car entry))) + (setq new-buffer (car entry)) (or (buffer-live-p new-buffer) (not (setq killed-buffers (cons new-buffer killed-buffers)))) - (not (eq new-buffer old-buffer)) (or (null pred) (funcall pred new-buffer))) (if (switch-to-prev-buffer-skip-p skip window new-buffer) (setq skipped (or skipped new-buffer)) @@ -4774,8 +4843,8 @@ This function is called by `next-buffer'." window new-buffer (nth 1 entry) (nth 2 entry)) (throw 'found t)))) - (when skipped - ;; Show first skipped buffer. + (when (and skipped (not (functionp switch-to-prev-buffer-skip))) + ;; Show first skipped buffer, unless skip was a function. (setq new-buffer skipped) (set-window-buffer-start-and-point window new-buffer))) @@ -4993,9 +5062,10 @@ window's lists of previous and next buffers." (all-frames (cond ((not frame) t) ((eq frame t) nil) (t frame)))) (dolist (window (window-list-1 nil nil all-frames)) (if (eq (window-buffer window) buffer) - (let ((deletable (window-deletable-p window))) + (let ((deletable (window-deletable-p window)) + (dedicated (window-dedicated-p window))) (cond - ((and (eq deletable 'frame) (window-dedicated-p window)) + ((and (eq deletable 'frame) dedicated) ;; Delete frame if and only if window is dedicated. (delete-frame (window-frame window))) ((eq deletable t) @@ -5004,7 +5074,10 @@ window's lists of previous and next buffers." (t ;; In window switch to previous buffer. (set-window-dedicated-p window nil) - (switch-to-prev-buffer window 'bury)))) + (switch-to-prev-buffer window 'bury) + ;; Restore the dedicated 'side' flag. + (when (eq dedicated 'side) + (set-window-dedicated-p window 'side))))) ;; If a window doesn't show BUFFER, unrecord BUFFER in it. (unrecord-window-buffer window buffer))))) @@ -5013,10 +5086,10 @@ window's lists of previous and next buffers." BUFFER-OR-NAME may be a buffer or the name of an existing buffer and defaults to the current buffer. -When a window showing BUFFER-OR-NAME is dedicated, that window is -deleted. If that window is the only window on its frame, the -frame is deleted too when there are other frames left. If there -are no other frames left, some other buffer is displayed in that +With the exception of side windows, when a window showing BUFFER-OR-NAME +is dedicated, that window is deleted. If that window is the only window +on its frame, the frame is deleted too when there are other frames left. +If there are no other frames left, some other buffer is displayed in that window. This function removes the buffer denoted by BUFFER-OR-NAME from @@ -5025,10 +5098,14 @@ all window-local buffer lists." (let ((buffer (window-normalize-buffer buffer-or-name))) (dolist (window (window-list-1 nil nil t)) (if (eq (window-buffer window) buffer) - (unless (window--delete window t t) - ;; Switch to another buffer in window. - (set-window-dedicated-p window nil) - (switch-to-prev-buffer window 'kill)) + ;; Delete a dedicated window unless it is a side window. + (let ((dedicated-side (eq (window-dedicated-p window) 'side))) + (when (or dedicated-side (not (window--delete window t t))) + ;; Switch to another buffer in that window. + (set-window-dedicated-p window nil) + (if (switch-to-prev-buffer window 'kill) + (and dedicated-side (set-window-dedicated-p window 'side)) + (window--delete window nil 'kill)))) ;; Unrecord BUFFER in WINDOW. (unrecord-window-buffer window buffer))))) @@ -5050,6 +5127,10 @@ buffer. If WINDOW is not deleted, reset its `quit-restore' parameter to nil. See Info node `(elisp) Quitting Windows' for more details. +If WINDOW's dedicated flag is t, try to delete WINDOW. If it +equals the value 'side', restore that value when WINDOW is not +deleted. + Optional second argument BURY-OR-KILL tells how to proceed with the buffer of WINDOW. The following values are handled: @@ -5072,16 +5153,16 @@ nil means to not handle the buffer in a particular way. This (setq window (window-normalize-window window t)) (let* ((buffer (window-buffer window)) (quit-restore (window-parameter window 'quit-restore)) - (prev-buffer - (let* ((prev-buffers (window-prev-buffers window)) - (prev-buffer (caar prev-buffers))) - (and (or (not (eq prev-buffer buffer)) - (and (cdr prev-buffers) - (not (eq (setq prev-buffer (cadr prev-buffers)) - buffer)))) - prev-buffer))) + (prev-buffer (catch 'prev-buffer + (dolist (buf (window-prev-buffers window)) + (unless (eq (car buf) buffer) + (throw 'prev-buffer (car buf)))))) + (dedicated (window-dedicated-p window)) quad entry) (cond + ;; First try to delete dedicated windows that are not side windows. + ((and dedicated (not (eq dedicated 'side)) + (window--delete window 'dedicated (eq bury-or-kill 'kill)))) ((and (not prev-buffer) (eq (nth 1 quit-restore) 'tab) (eq (nth 3 quit-restore) buffer)) @@ -5124,6 +5205,9 @@ nil means to not handle the buffer in a particular way. This ;; Restore WINDOW's previous buffer, start and point position. (set-window-buffer-start-and-point window (nth 0 quad) (nth 1 quad) (nth 2 quad)) + ;; Restore the 'side' dedicated flag as well. + (when (eq dedicated 'side) + (set-window-dedicated-p window 'side)) ;; Deal with the buffer we just removed from WINDOW. (setq entry (and (eq bury-or-kill 'append) (assq buffer (window-prev-buffers window)))) @@ -5150,7 +5234,14 @@ nil means to not handle the buffer in a particular way. This (set-window-parameter window 'quit-restore nil) ;; Make sure that WINDOW is no more dedicated. (set-window-dedicated-p window nil) - (switch-to-prev-buffer window bury-or-kill))) + ;; Try to switch to a previous buffer. Delete the window only if + ;; that is not possible (Bug#48367). + (if (switch-to-prev-buffer window bury-or-kill) + (when (eq dedicated 'side) + (set-window-dedicated-p window 'side)) + (window--delete window nil (eq bury-or-kill 'kill)) + (when (window-live-p (nth 2 quit-restore)) + (select-window (nth 2 quit-restore)))))) ;; Deal with the buffer. (cond @@ -6171,29 +6262,27 @@ value can be also stored on disk and read back in a new session." ;; Select window if it's the selected one. (when (cdr (assq 'selected state)) (select-window window)) - (when next-buffers - (set-window-next-buffers - window - (delq nil (mapcar (lambda (buffer) - (setq buffer (get-buffer buffer)) - (when (buffer-live-p buffer) buffer)) - next-buffers)))) - (when prev-buffers - (set-window-prev-buffers - window - (delq nil (mapcar (lambda (entry) - (let ((buffer (get-buffer (nth 0 entry))) - (m1 (nth 1 entry)) - (m2 (nth 2 entry))) - (when (buffer-live-p buffer) - (list buffer - (if (markerp m1) m1 - (set-marker (make-marker) m1 - buffer)) - (if (markerp m2) m2 - (set-marker (make-marker) m2 - buffer)))))) - prev-buffers))))) + (set-window-next-buffers + window + (delq nil (mapcar (lambda (buffer) + (setq buffer (get-buffer buffer)) + (when (buffer-live-p buffer) buffer)) + next-buffers))) + (set-window-prev-buffers + window + (delq nil (mapcar (lambda (entry) + (let ((buffer (get-buffer (nth 0 entry))) + (m1 (nth 1 entry)) + (m2 (nth 2 entry))) + (when (buffer-live-p buffer) + (list buffer + (if (markerp m1) m1 + (set-marker (make-marker) m1 + buffer)) + (if (markerp m2) m2 + (set-marker (make-marker) m2 + buffer)))))) + prev-buffers)))) ;; We don't want to raise an error in case the buffer does ;; not exist anymore, so we switch to a previous one and ;; save the window with the intention of deleting it later @@ -7410,8 +7499,8 @@ For instance: Buffer display can be further customized to a very high degree; the rest of this docstring explains some of the many -possibilities, and also see `(emacs)Window Choice' for more -information. +possibilities, and also see Info node `(emacs)Window Choice' for +more information. BUFFER-OR-NAME must be a buffer or a string naming a live buffer. Return the window chosen for displaying that buffer, or nil if no @@ -8645,6 +8734,13 @@ documentation for additional customization information." BUFFER-OR-NAME may be a buffer, a string (a buffer name), or nil. Return the buffer switched to. +This uses the function `display-buffer' as a subroutine to +display the buffer; see its documentation for additional +customization information. By default, if the buffer is already +displayed (even in the current frame), that window is selected. +If the buffer isn't displayed in any frame, a new frame is popped +up and the buffer is displayed there. + If called interactively, read the buffer name using `read-buffer'. The variable `confirm-nonexistent-file-or-buffer' determines whether to request confirmation before creating a new buffer. @@ -8656,10 +8752,7 @@ buffer, create a new buffer with that name. If BUFFER-OR-NAME is nil, switch to the buffer returned by `other-buffer'. Optional second arg NORECORD non-nil means do not put this -buffer at the front of the list of recently selected ones. - -This uses the function `display-buffer' as a subroutine; see its -documentation for additional customization information." +buffer at the front of the list of recently selected ones." (interactive (list (read-buffer-to-switch "Switch to buffer in other frame: "))) (pop-to-buffer buffer-or-name display-buffer--other-frame-action norecord)) @@ -8673,11 +8766,14 @@ meaning of these values in `window--display-buffer'. Optional `post-function' is called after the buffer is displayed in the window; the function takes two arguments: an old and new window. Optional string argument `echo' can be used to add a prefix to the -command echo keystrokes that should describe the current prefix state." +command echo keystrokes that should describe the current prefix state. +This returns an \"exit function\", which can be called with no argument +to deactivate this overriding action." (let* ((old-window (or (minibuffer-selected-window) (selected-window))) (new-window nil) (minibuffer-depth (minibuffer-depth)) (clearfun (make-symbol "clear-display-buffer-overriding-action")) + (postfun (make-symbol "post-display-buffer-override-next-command")) (action (lambda (buffer alist) (unless (> (minibuffer-depth) minibuffer-depth) (let* ((ret (funcall pre-function buffer alist)) @@ -8686,22 +8782,24 @@ command echo keystrokes that should describe the current prefix state." (setq new-window (window--display-buffer buffer window type alist)) ;; Reset display-buffer-overriding-action - ;; after the first buffer display action + ;; after the first display-buffer action (bug#39722). (funcall clearfun) - (setq post-function nil) new-window)))) (command this-command) (echofun (when echo (lambda () echo))) (exitfun (lambda () - (setcar display-buffer-overriding-action - (delq action (car display-buffer-overriding-action))) - (remove-hook 'post-command-hook clearfun) + (funcall clearfun) + (remove-hook 'post-command-hook postfun) (remove-hook 'prefix-command-echo-keystrokes-functions echofun) (when (functionp post-function) (funcall post-function old-window new-window))))) (fset clearfun (lambda () + (setcar display-buffer-overriding-action + (delq action (car display-buffer-overriding-action))))) + (fset postfun + (lambda () (unless (or ;; Remove the hook immediately ;; after exiting the minibuffer. @@ -8710,12 +8808,12 @@ command echo keystrokes that should describe the current prefix state." ;; adding the hook by the same command below. (eq this-command command)) (funcall exitfun)))) - ;; Reset display-buffer-overriding-action - ;; after the next command finishes - (add-hook 'post-command-hook clearfun) + ;; Call post-function after the next command finishes (bug#49057). + (add-hook 'post-command-hook postfun) (when echofun (add-hook 'prefix-command-echo-keystrokes-functions echofun)) - (push action (car display-buffer-overriding-action)))) + (push action (car display-buffer-overriding-action)) + exitfun)) (defun set-window-text-height (window height) @@ -8825,7 +8923,11 @@ font on WINDOW's frame." (let* ((window (window-normalize-window window t)) (frame (window-frame window)) (default-font (face-font 'default frame))) - (if (and (display-multi-font-p (frame-parameter frame 'display)) + ;; Client frames can have the 'display' parameter set like for X + ;; frames, even though they are TTY frames, so make sure we won't + ;; be duped by that up front with 'framep'. + (if (and (not (eq (framep frame) t)) + (display-multi-font-p (frame-parameter frame 'display)) (not (string-equal (frame-parameter frame 'font) default-font))) (aref (font-info default-font frame) 3) (frame-char-height frame)))) @@ -10088,6 +10190,9 @@ is active. This function is run by `mouse-autoselect-window-timer'." ;; already selected. (and (not (eq frame (selected-frame))) (frame-parameter frame 'no-accept-focus)) + ;; Don't switch if window autoselection with mouse is active + ;; and minibuffer window is selected. + (and mouse-autoselect-window (window-minibuffer-p)) ;; Don't switch to minibuffer window unless it's active. (and (window-minibuffer-p window) (not (minibuffer-window-active-p window)))) @@ -10252,6 +10357,32 @@ displaying that processes's buffer." (define-key ctl-x-4-map "1" 'same-window-prefix) (define-key ctl-x-4-map "4" 'other-window-prefix) +(defvar other-window-repeat-map + (let ((map (make-sparse-keymap))) + (define-key map "o" 'other-window) + (define-key map "O" (lambda () + (interactive) + (setq repeat-map 'other-window-repeat-map) + (other-window -1))) + map) + "Keymap to repeat other-window key sequences. Used in `repeat-mode'.") +(put 'other-window 'repeat-map 'other-window-repeat-map) + +(defvar resize-window-repeat-map + (let ((map (make-sparse-keymap))) + ;; Standard keys: + (define-key map "^" 'enlarge-window) + (define-key map "}" 'enlarge-window-horizontally) + (define-key map "{" 'shrink-window-horizontally) + ;; Additional keys: + (define-key map "v" 'shrink-window) + map) + "Keymap to repeat window resizing commands. Used in `repeat-mode'.") +(put 'enlarge-window 'repeat-map 'resize-window-repeat-map) +(put 'enlarge-window-horizontally 'repeat-map 'resize-window-repeat-map) +(put 'shrink-window-horizontally 'repeat-map 'resize-window-repeat-map) +(put 'shrink-window 'repeat-map 'resize-window-repeat-map) + (provide 'window) ;;; window.el ends here |