diff options
| author | Martin Rudalics | 2021-06-10 09:14:21 +0200 |
|---|---|---|
| committer | Martin Rudalics | 2021-06-10 09:14:21 +0200 |
| commit | b3dd0ce75ba9314eb7a682e5fcf8b4cfbc67655b (patch) | |
| tree | ab7873f3a18ce3873200863e37fed9534558ce93 | |
| parent | dd9385b404c28a155a91960a4f1c4c77fdc5413d (diff) | |
| download | emacs-b3dd0ce75ba9314eb7a682e5fcf8b4cfbc67655b.tar.gz emacs-b3dd0ce75ba9314eb7a682e5fcf8b4cfbc67655b.zip | |
Provide new option `delete-window-set-selected' (Bug#47300)
When `delete-window' deletes its frame's selected window, this new
option allows to choose another window as replacement.
* lisp/window.el (get-lru-window, get-mru-window)
(get-largest-window): New optional argument NO-OTHER.
(window-at-pos): New function.
(delete-window-set-selected): New option.
(delete-window): Handle `delete-window-set-selected'.
* src/window.c (Fdelete_window_internal): Set the selected
window of WINDOW's frame to the first window on that frame and
let `delete-window' choose a more suitable window instead.
* doc/lispref/windows.texi (Deleting Windows): Describe new
option `delete-window-set-selected'.
(Cyclic Window Ordering): Describe new NO-OTHER argument for
`get-lru-window', `get-mru-window' and `get-largest-window'.
* etc/NEWS: Mention `delete-window-set-selected' and the NO-OTHER
argument.
| -rw-r--r-- | doc/lispref/windows.texi | 47 | ||||
| -rw-r--r-- | etc/NEWS | 11 | ||||
| -rw-r--r-- | lisp/window.el | 157 | ||||
| -rw-r--r-- | src/window.c | 25 |
4 files changed, 171 insertions, 69 deletions
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 44656c057a3..bcb492d68f7 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi | |||
| @@ -1318,6 +1318,23 @@ lieu of the usual action of @code{delete-window}. @xref{Window | |||
| 1318 | Parameters}. | 1318 | Parameters}. |
| 1319 | @end deffn | 1319 | @end deffn |
| 1320 | 1320 | ||
| 1321 | When @code{delete-window} deletes the selected window of its frame, it | ||
| 1322 | has to make another window the new selected window of that frame. The | ||
| 1323 | following option allows to choose which window gets selected instead. | ||
| 1324 | |||
| 1325 | @defopt delete-window-set-selected | ||
| 1326 | This option allows to specify which window should become a frame's | ||
| 1327 | selected window after @code{delete-window} has deleted the previously | ||
| 1328 | selected one. | ||
| 1329 | |||
| 1330 | Possible choices are @code{mru} (the default) to select the most | ||
| 1331 | recently used window on that frame and @code{pos} to choose the window | ||
| 1332 | at the position of point of the previously selected window. If this | ||
| 1333 | option is @code{nil}, it means to choose the frame's first window | ||
| 1334 | instead. Note that a window with a non-@code{nil} | ||
| 1335 | @code{no-other-window} parameter is never chosen. | ||
| 1336 | @end defopt | ||
| 1337 | |||
| 1321 | @deffn Command delete-other-windows &optional window | 1338 | @deffn Command delete-other-windows &optional window |
| 1322 | This function makes @var{window} fill its frame, deleting other | 1339 | This function makes @var{window} fill its frame, deleting other |
| 1323 | windows as necessary. If @var{window} is omitted or @code{nil}, it | 1340 | windows as necessary. If @var{window} is omitted or @code{nil}, it |
| @@ -2007,7 +2024,7 @@ meaning as for @code{next-window}. | |||
| 2007 | criterion, without selecting it: | 2024 | criterion, without selecting it: |
| 2008 | 2025 | ||
| 2009 | @cindex least recently used window | 2026 | @cindex least recently used window |
| 2010 | @defun get-lru-window &optional all-frames dedicated not-selected | 2027 | @defun get-lru-window &optional all-frames dedicated not-selected no-other |
| 2011 | This function returns a live window which is heuristically the least | 2028 | This function returns a live window which is heuristically the least |
| 2012 | recently used. The optional argument @var{all-frames} has | 2029 | recently used. The optional argument @var{all-frames} has |
| 2013 | the same meaning as in @code{next-window}. | 2030 | the same meaning as in @code{next-window}. |
| @@ -2018,33 +2035,25 @@ window (@pxref{Dedicated Windows}) is never a candidate unless the | |||
| 2018 | optional argument @var{dedicated} is non-@code{nil}. The selected | 2035 | optional argument @var{dedicated} is non-@code{nil}. The selected |
| 2019 | window is never returned, unless it is the only candidate. However, if | 2036 | window is never returned, unless it is the only candidate. However, if |
| 2020 | the optional argument @var{not-selected} is non-@code{nil}, this | 2037 | the optional argument @var{not-selected} is non-@code{nil}, this |
| 2021 | function returns @code{nil} in that case. | 2038 | function returns @code{nil} in that case. The optional argument |
| 2039 | @var{no-other}, if non-@code{nil}, means to never return a window whose | ||
| 2040 | @code{no-other-window} parameter is non-@code{nil}. | ||
| 2022 | @end defun | 2041 | @end defun |
| 2023 | 2042 | ||
| 2024 | @cindex most recently used window | 2043 | @cindex most recently used window |
| 2025 | @defun get-mru-window &optional all-frames dedicated not-selected | 2044 | @defun get-mru-window &optional all-frames dedicated not-selected no-other |
| 2026 | This function is like @code{get-lru-window}, but it returns the most | 2045 | This function is like @code{get-lru-window}, but it returns the most |
| 2027 | recently used window instead. The meaning of the arguments is the | 2046 | recently used window instead. The meaning of the arguments is the |
| 2028 | same as described for @code{get-lru-window}. | 2047 | same as for @code{get-lru-window}. |
| 2029 | @end defun | 2048 | @end defun |
| 2030 | 2049 | ||
| 2031 | @cindex largest window | 2050 | @cindex largest window |
| 2032 | @defun get-largest-window &optional all-frames dedicated not-selected | 2051 | @defun get-largest-window &optional all-frames dedicated not-selected no-other |
| 2033 | This function returns the window with the largest area (height times | 2052 | This function returns the window with the largest area (height times |
| 2034 | width). The optional argument @var{all-frames} specifies the windows to | 2053 | width). If there are two candidate windows of the same size, it prefers |
| 2035 | search, and has the same meaning as in @code{next-window}. | 2054 | the one that comes first in the cyclic ordering of windows, starting |
| 2036 | 2055 | from the selected window. The meaning of the arguments is the same as | |
| 2037 | A minibuffer window is never a candidate. A dedicated window | 2056 | for @code{get-lru-window}. |
| 2038 | (@pxref{Dedicated Windows}) is never a candidate unless the optional | ||
| 2039 | argument @var{dedicated} is non-@code{nil}. The selected window is not | ||
| 2040 | a candidate if the optional argument @var{not-selected} is | ||
| 2041 | non-@code{nil}. If the optional argument @var{not-selected} is | ||
| 2042 | non-@code{nil} and the selected window is the only candidate, this | ||
| 2043 | function returns @code{nil}. | ||
| 2044 | |||
| 2045 | If there are two candidate windows of the same size, this function | ||
| 2046 | prefers the one that comes first in the cyclic ordering of windows, | ||
| 2047 | starting from the selected window. | ||
| 2048 | @end defun | 2057 | @end defun |
| 2049 | 2058 | ||
| 2050 | @cindex window that satisfies a predicate | 2059 | @cindex window that satisfies a predicate |
| @@ -605,6 +605,17 @@ These options include 'windmove-default-keybindings', | |||
| 605 | ** Windows | 605 | ** Windows |
| 606 | 606 | ||
| 607 | +++ | 607 | +++ |
| 608 | *** New option 'delete-window-set-selected'. | ||
| 609 | This allows to choose a frame's selected window after deleting the | ||
| 610 | previously selected one. | ||
| 611 | |||
| 612 | +++ | ||
| 613 | *** New argument NO-OTHER for some window functions. | ||
| 614 | 'get-lru-window', ‘get-mru-window’ and 'get-largest-window' now accept a | ||
| 615 | new optional argument NO-OTHER which if non-nil avoids returning a | ||
| 616 | window whose 'no-other-window' parameter is non-nil. | ||
| 617 | |||
| 618 | +++ | ||
| 608 | *** New 'display-buffer' function 'display-buffer-use-least-recent-window'. | 619 | *** New 'display-buffer' function 'display-buffer-use-least-recent-window'. |
| 609 | This is like 'display-buffer-use-some-window', but won't reuse the | 620 | This is like 'display-buffer-use-some-window', but won't reuse the |
| 610 | current window, and when called repeatedly will try not to reuse a | 621 | current window, and when called repeatedly will try not to reuse a |
diff --git a/lisp/window.el b/lisp/window.el index fd1c617d6be..e7551f30c32 100644 --- a/lisp/window.el +++ b/lisp/window.el | |||
| @@ -2499,14 +2499,16 @@ and no others." | |||
| 2499 | 2499 | ||
| 2500 | (defalias 'some-window 'get-window-with-predicate) | 2500 | (defalias 'some-window 'get-window-with-predicate) |
| 2501 | 2501 | ||
| 2502 | (defun get-lru-window (&optional all-frames dedicated not-selected) | 2502 | (defun get-lru-window (&optional all-frames dedicated not-selected no-other) |
| 2503 | "Return the least recently used window on frames specified by ALL-FRAMES. | 2503 | "Return the least recently used window on frames specified by ALL-FRAMES. |
| 2504 | Return a full-width window if possible. A minibuffer window is | 2504 | Return a full-width window if possible. A minibuffer window is |
| 2505 | never a candidate. A dedicated window is never a candidate | 2505 | never a candidate. A dedicated window is never a candidate |
| 2506 | unless DEDICATED is non-nil, so if all windows are dedicated, the | 2506 | unless DEDICATED is non-nil, so if all windows are dedicated, the |
| 2507 | value is nil. Avoid returning the selected window if possible. | 2507 | value is nil. Avoid returning the selected window if possible. |
| 2508 | Optional argument NOT-SELECTED non-nil means never return the | 2508 | Optional argument NOT-SELECTED non-nil means never return the |
| 2509 | selected window. | 2509 | selected window. Optional argument NO-OTHER non-nil means to |
| 2510 | never return a window whose 'no-other-window' parameter is | ||
| 2511 | non-nil. | ||
| 2510 | 2512 | ||
| 2511 | The following non-nil values of the optional argument ALL-FRAMES | 2513 | The following non-nil values of the optional argument ALL-FRAMES |
| 2512 | have special meanings: | 2514 | have special meanings: |
| @@ -2526,7 +2528,9 @@ selected frame and no others." | |||
| 2526 | (let (best-window best-time second-best-window second-best-time time) | 2528 | (let (best-window best-time second-best-window second-best-time time) |
| 2527 | (dolist (window (window-list-1 nil 'nomini all-frames)) | 2529 | (dolist (window (window-list-1 nil 'nomini all-frames)) |
| 2528 | (when (and (or dedicated (not (window-dedicated-p window))) | 2530 | (when (and (or dedicated (not (window-dedicated-p window))) |
| 2529 | (or (not not-selected) (not (eq window (selected-window))))) | 2531 | (or (not not-selected) (not (eq window (selected-window)))) |
| 2532 | (or (not no-other) | ||
| 2533 | (not (window-parameter window 'no-other-window)))) | ||
| 2530 | (setq time (window-use-time window)) | 2534 | (setq time (window-use-time window)) |
| 2531 | (if (or (eq window (selected-window)) | 2535 | (if (or (eq window (selected-window)) |
| 2532 | (not (window-full-width-p window))) | 2536 | (not (window-full-width-p window))) |
| @@ -2538,12 +2542,14 @@ selected frame and no others." | |||
| 2538 | (setq best-window window))))) | 2542 | (setq best-window window))))) |
| 2539 | (or best-window second-best-window))) | 2543 | (or best-window second-best-window))) |
| 2540 | 2544 | ||
| 2541 | (defun get-mru-window (&optional all-frames dedicated not-selected) | 2545 | (defun get-mru-window (&optional all-frames dedicated not-selected no-other) |
| 2542 | "Return the most recently used window on frames specified by ALL-FRAMES. | 2546 | "Return the most recently used window on frames specified by ALL-FRAMES. |
| 2543 | A minibuffer window is never a candidate. A dedicated window is | 2547 | A minibuffer window is never a candidate. A dedicated window is |
| 2544 | never a candidate unless DEDICATED is non-nil, so if all windows | 2548 | never a candidate unless DEDICATED is non-nil, so if all windows |
| 2545 | are dedicated, the value is nil. Optional argument NOT-SELECTED | 2549 | are dedicated, the value is nil. Optional argument NOT-SELECTED |
| 2546 | non-nil means never return the selected window. | 2550 | non-nil means never return the selected window. Optional |
| 2551 | argument NO-OTHER non-nil means to never return a window whose | ||
| 2552 | 'no-other-window' parameter is non-nil. | ||
| 2547 | 2553 | ||
| 2548 | The following non-nil values of the optional argument ALL-FRAMES | 2554 | The following non-nil values of the optional argument ALL-FRAMES |
| 2549 | have special meanings: | 2555 | have special meanings: |
| @@ -2565,17 +2571,21 @@ selected frame and no others." | |||
| 2565 | (setq time (window-use-time window)) | 2571 | (setq time (window-use-time window)) |
| 2566 | (when (and (or dedicated (not (window-dedicated-p window))) | 2572 | (when (and (or dedicated (not (window-dedicated-p window))) |
| 2567 | (or (not not-selected) (not (eq window (selected-window)))) | 2573 | (or (not not-selected) (not (eq window (selected-window)))) |
| 2568 | (or (not best-time) (> time best-time))) | 2574 | (or (not no-other) |
| 2575 | (not (window-parameter window 'no-other-window))) | ||
| 2576 | (or (not best-time) (> time best-time))) | ||
| 2569 | (setq best-time time) | 2577 | (setq best-time time) |
| 2570 | (setq best-window window))) | 2578 | (setq best-window window))) |
| 2571 | best-window)) | 2579 | best-window)) |
| 2572 | 2580 | ||
| 2573 | (defun get-largest-window (&optional all-frames dedicated not-selected) | 2581 | (defun get-largest-window (&optional all-frames dedicated not-selected no-other) |
| 2574 | "Return the largest window on frames specified by ALL-FRAMES. | 2582 | "Return the largest window on frames specified by ALL-FRAMES. |
| 2575 | A minibuffer window is never a candidate. A dedicated window is | 2583 | A minibuffer window is never a candidate. A dedicated window is |
| 2576 | never a candidate unless DEDICATED is non-nil, so if all windows | 2584 | never a candidate unless DEDICATED is non-nil, so if all windows |
| 2577 | are dedicated, the value is nil. Optional argument NOT-SELECTED | 2585 | are dedicated, the value is nil. Optional argument NOT-SELECTED |
| 2578 | non-nil means never return the selected window. | 2586 | non-nil means never return the selected window. Optional |
| 2587 | argument NO-OTHER non-nil means to never return a window whose | ||
| 2588 | 'no-other-window' parameter is non-nil. | ||
| 2579 | 2589 | ||
| 2580 | The following non-nil values of the optional argument ALL-FRAMES | 2590 | The following non-nil values of the optional argument ALL-FRAMES |
| 2581 | have special meanings: | 2591 | have special meanings: |
| @@ -2596,7 +2606,9 @@ selected frame and no others." | |||
| 2596 | best-window size) | 2606 | best-window size) |
| 2597 | (dolist (window (window-list-1 nil 'nomini all-frames)) | 2607 | (dolist (window (window-list-1 nil 'nomini all-frames)) |
| 2598 | (when (and (or dedicated (not (window-dedicated-p window))) | 2608 | (when (and (or dedicated (not (window-dedicated-p window))) |
| 2599 | (or (not not-selected) (not (eq window (selected-window))))) | 2609 | (or (not not-selected) (not (eq window (selected-window)))) |
| 2610 | (or (not no-other) | ||
| 2611 | (not (window-parameter window 'no-other-window)))) | ||
| 2600 | (setq size (* (window-pixel-height window) | 2612 | (setq size (* (window-pixel-height window) |
| 2601 | (window-pixel-width window))) | 2613 | (window-pixel-width window))) |
| 2602 | (when (> size best-size) | 2614 | (when (> size best-size) |
| @@ -4130,18 +4142,53 @@ frame can be safely deleted." | |||
| 4130 | ;; of its frame. | 4142 | ;; of its frame. |
| 4131 | t)))) | 4143 | t)))) |
| 4132 | 4144 | ||
| 4133 | (defun window--in-subtree-p (window root) | 4145 | (defun window-at-pos (x y &optional frame no-other) |
| 4134 | "Return t if WINDOW is either ROOT or a member of ROOT's subtree." | 4146 | "Return live window at coordinates X, Y on specified FRAME. |
| 4135 | (or (eq window root) | 4147 | X and Y are counted in pixels from an origin at 0, 0 of FRAME's |
| 4136 | (let ((parent (window-parent window))) | 4148 | native frame. A coordinate on an edge shared by two windows is |
| 4137 | (catch 'done | 4149 | attributed to the window on the right (or below). Return nil if |
| 4138 | (while parent | 4150 | no such window can be found. |
| 4139 | (if (eq parent root) | 4151 | |
| 4140 | (throw 'done t) | 4152 | Optional argument FRAME must specify a live frame and defaults to |
| 4141 | (setq parent (window-parent parent)))))))) | 4153 | the selected one. Optional argument NO-OTHER non-nil means to |
| 4154 | not return a window with a non-nil 'no-other-window' parameter." | ||
| 4155 | (setq frame (window-normalize-frame frame)) | ||
| 4156 | (let* ((root-edges (window-edges (frame-root-window frame) nil nil t)) | ||
| 4157 | (root-left (nth 2 root-edges)) | ||
| 4158 | (root-bottom (nth 3 root-edges))) | ||
| 4159 | (catch 'window | ||
| 4160 | (walk-window-tree | ||
| 4161 | (lambda (window) | ||
| 4162 | (let ((edges (window-edges window nil nil t))) | ||
| 4163 | (when (and (>= x (nth 0 edges)) | ||
| 4164 | (or (< x (nth 2 edges)) (= x root-left)) | ||
| 4165 | (>= y (nth 1 edges)) | ||
| 4166 | (or (< y (nth 3 edges)) (= y root-bottom))) | ||
| 4167 | (if (and no-other (window-parameter window 'no-other-window)) | ||
| 4168 | (throw 'window nil) | ||
| 4169 | (throw 'window window))))) | ||
| 4170 | frame)))) | ||
| 4171 | |||
| 4172 | (defcustom delete-window-set-selected 'mru | ||
| 4173 | "How to choose a frame's selected window after window deletion. | ||
| 4174 | When a frame's selected window gets deleted, Emacs has to choose | ||
| 4175 | another live window on that frame to serve as its selected | ||
| 4176 | window. This option allows to control which window gets selected | ||
| 4177 | instead. | ||
| 4178 | |||
| 4179 | The possible choices are 'mru' (the default) to select the most | ||
| 4180 | recently used window on that frame and 'pos' to choose the window | ||
| 4181 | at the position of point of the previously selected window. If | ||
| 4182 | this is nil, choose the frame's first window instead. A window | ||
| 4183 | with a non-nil 'no-other-window' parameter is never chosen." | ||
| 4184 | :type '(choice (const :tag "Most recently used" mru) | ||
| 4185 | (const :tag "At position of deleted" pos) | ||
| 4186 | (const :tag "Frame's first " nil)) | ||
| 4187 | :group 'windows | ||
| 4188 | :version "28.1") | ||
| 4142 | 4189 | ||
| 4143 | (defun delete-window (&optional window) | 4190 | (defun delete-window (&optional window) |
| 4144 | "Delete WINDOW. | 4191 | "Delete specified WINDOW. |
| 4145 | WINDOW must be a valid window and defaults to the selected one. | 4192 | WINDOW must be a valid window and defaults to the selected one. |
| 4146 | Return nil. | 4193 | Return nil. |
| 4147 | 4194 | ||
| @@ -4156,7 +4203,11 @@ Otherwise, if WINDOW is part of an atomic window, call | |||
| 4156 | `delete-window' with the root of the atomic window as its | 4203 | `delete-window' with the root of the atomic window as its |
| 4157 | argument. Signal an error if WINDOW is either the only window on | 4204 | argument. Signal an error if WINDOW is either the only window on |
| 4158 | its frame, the last non-side window, or part of an atomic window | 4205 | its frame, the last non-side window, or part of an atomic window |
| 4159 | that is its frame's root window." | 4206 | that is its frame's root window. |
| 4207 | |||
| 4208 | If WINDOW is the selected window on its frame, choose some other | ||
| 4209 | window as that frame's selected window according to the value of | ||
| 4210 | the option `delete-window-set-selected'." | ||
| 4160 | (interactive) | 4211 | (interactive) |
| 4161 | (setq window (window-normalize-window window)) | 4212 | (setq window (window-normalize-window window)) |
| 4162 | (let* ((frame (window-frame window)) | 4213 | (let* ((frame (window-frame window)) |
| @@ -4191,11 +4242,11 @@ that is its frame's root window." | |||
| 4191 | (window-combination-resize | 4242 | (window-combination-resize |
| 4192 | (or window-combination-resize | 4243 | (or window-combination-resize |
| 4193 | (window-parameter parent 'window-side))) | 4244 | (window-parameter parent 'window-side))) |
| 4194 | (frame-selected | 4245 | (frame-selected-window (frame-selected-window frame)) |
| 4195 | (window--in-subtree-p (frame-selected-window frame) window)) | ||
| 4196 | ;; Emacs 23 preferably gives WINDOW's space to its left | 4246 | ;; Emacs 23 preferably gives WINDOW's space to its left |
| 4197 | ;; sibling. | 4247 | ;; sibling. |
| 4198 | (sibling (or (window-left window) (window-right window)))) | 4248 | (sibling (or (window-left window) (window-right window))) |
| 4249 | frame-selected-window-edges frame-selected-window-pos) | ||
| 4199 | (window--resize-reset frame horizontal) | 4250 | (window--resize-reset frame horizontal) |
| 4200 | (cond | 4251 | (cond |
| 4201 | ((and (not (eq window-combination-resize t)) | 4252 | ((and (not (eq window-combination-resize t)) |
| @@ -4211,15 +4262,63 @@ that is its frame's root window." | |||
| 4211 | (t | 4262 | (t |
| 4212 | ;; Can't do without resizing fixed-size windows. | 4263 | ;; Can't do without resizing fixed-size windows. |
| 4213 | (window--resize-siblings window (- size) horizontal t))) | 4264 | (window--resize-siblings window (- size) horizontal t))) |
| 4265 | |||
| 4266 | (when (eq delete-window-set-selected 'pos) | ||
| 4267 | ;; Remember edges and position of point of the selected window | ||
| 4268 | ;; of WINDOW'S frame. | ||
| 4269 | (setq frame-selected-window-edges | ||
| 4270 | (window-edges frame-selected-window nil nil t)) | ||
| 4271 | (setq frame-selected-window-pos | ||
| 4272 | (nth 2 (posn-at-point nil frame-selected-window)))) | ||
| 4273 | |||
| 4214 | ;; Actually delete WINDOW. | 4274 | ;; Actually delete WINDOW. |
| 4215 | (delete-window-internal window) | 4275 | (delete-window-internal window) |
| 4216 | (window--pixel-to-total frame horizontal) | 4276 | (window--pixel-to-total frame horizontal) |
| 4217 | (when (and frame-selected | 4277 | |
| 4218 | (window-parameter | 4278 | ;; If we deleted the selected window of WINDOW's frame, choose |
| 4219 | (frame-selected-window frame) 'no-other-window)) | 4279 | ;; another one based on `delete-window-set-selected'. Note |
| 4220 | ;; `delete-window-internal' has selected a window that should | 4280 | ;; that both `window-at-pos' and `get-mru-window' may fail to |
| 4221 | ;; not be selected, fix this here. | 4281 | ;; produce a suitable window in which case we will fall back on |
| 4222 | (other-window -1 frame)) | 4282 | ;; its frame's first window, chosen by `delete-window-internal'. |
| 4283 | (cond | ||
| 4284 | ((window-live-p frame-selected-window)) | ||
| 4285 | ((and frame-selected-window-pos | ||
| 4286 | ;; We have a recorded position of point of the previously | ||
| 4287 | ;; selected window. Try to find the window that is now | ||
| 4288 | ;; at that position. | ||
| 4289 | (let ((new-frame-selected-window | ||
| 4290 | (window-at-pos | ||
| 4291 | (+ (nth 0 frame-selected-window-edges) | ||
| 4292 | (car frame-selected-window-pos)) | ||
| 4293 | (+ (nth 1 frame-selected-window-edges) | ||
| 4294 | (cdr frame-selected-window-pos)) | ||
| 4295 | frame t))) | ||
| 4296 | (and new-frame-selected-window | ||
| 4297 | ;; Select window at WINDOW's position at point. | ||
| 4298 | (set-frame-selected-window | ||
| 4299 | frame new-frame-selected-window))))) | ||
| 4300 | ((and (eq delete-window-set-selected 'mru) | ||
| 4301 | ;; Try to use the most recently used window. | ||
| 4302 | (let ((mru-window (get-mru-window frame nil nil t))) | ||
| 4303 | (and mru-window | ||
| 4304 | (set-frame-selected-window frame mru-window))))) | ||
| 4305 | ((and (window-parameter | ||
| 4306 | (frame-selected-window frame) 'no-other-window) | ||
| 4307 | ;; If `delete-window-internal' selected a window with a | ||
| 4308 | ;; non-nil 'no-other-window' parameter as its frame's | ||
| 4309 | ;; selected window, try to choose another one. | ||
| 4310 | (catch 'found | ||
| 4311 | (walk-window-tree | ||
| 4312 | (lambda (other) | ||
| 4313 | (unless (window-parameter other 'no-other-window) | ||
| 4314 | (set-frame-selected-window frame other) | ||
| 4315 | (throw 'found t))) | ||
| 4316 | frame)))) | ||
| 4317 | (t | ||
| 4318 | ;; Record the window chosen by `delete-window-internal'. | ||
| 4319 | (set-frame-selected-window | ||
| 4320 | frame (frame-selected-window frame)))) | ||
| 4321 | |||
| 4223 | (window--check frame) | 4322 | (window--check frame) |
| 4224 | ;; Always return nil. | 4323 | ;; Always return nil. |
| 4225 | nil)))) | 4324 | nil)))) |
diff --git a/src/window.c b/src/window.c index 2d98ae5f156..db324effcce 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -5148,15 +5148,13 @@ Signal an error when WINDOW is the only window on its frame. */) | |||
| 5148 | adjust_frame_glyphs (f); | 5148 | adjust_frame_glyphs (f); |
| 5149 | 5149 | ||
| 5150 | if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f))) | 5150 | if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f))) |
| 5151 | /* We deleted the frame's selected window. */ | 5151 | /* We apparently deleted the frame's selected window; use the |
| 5152 | frame's first window as substitute but don't record it yet. | ||
| 5153 | `delete-window' may have something better up its sleeves. */ | ||
| 5152 | { | 5154 | { |
| 5153 | /* Use the frame's first window as fallback ... */ | 5155 | /* Use the frame's first window as fallback ... */ |
| 5154 | Lisp_Object new_selected_window = Fframe_first_window (frame); | 5156 | Lisp_Object new_selected_window = Fframe_first_window (frame); |
| 5155 | /* ... but preferably use its most recently used window. */ | ||
| 5156 | Lisp_Object mru_window; | ||
| 5157 | 5157 | ||
| 5158 | /* `get-mru-window' might fail for some reason so play it safe | ||
| 5159 | - promote the first window _without recording it_ first. */ | ||
| 5160 | if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) | 5158 | if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) |
| 5161 | Fselect_window (new_selected_window, Qt); | 5159 | Fselect_window (new_selected_window, Qt); |
| 5162 | else | 5160 | else |
| @@ -5164,24 +5162,9 @@ Signal an error when WINDOW is the only window on its frame. */) | |||
| 5164 | last selected window on F was an active minibuffer, we | 5162 | last selected window on F was an active minibuffer, we |
| 5165 | want to return to it on a later Fselect_frame. */ | 5163 | want to return to it on a later Fselect_frame. */ |
| 5166 | fset_selected_window (f, new_selected_window); | 5164 | fset_selected_window (f, new_selected_window); |
| 5167 | |||
| 5168 | unblock_input (); | ||
| 5169 | |||
| 5170 | /* Now look whether `get-mru-window' gets us something. */ | ||
| 5171 | mru_window = call1 (Qget_mru_window, frame); | ||
| 5172 | if (WINDOW_LIVE_P (mru_window) | ||
| 5173 | && EQ (XWINDOW (mru_window)->frame, frame)) | ||
| 5174 | new_selected_window = mru_window; | ||
| 5175 | |||
| 5176 | /* If all ended up well, we now promote the mru window. */ | ||
| 5177 | if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) | ||
| 5178 | Fselect_window (new_selected_window, Qnil); | ||
| 5179 | else | ||
| 5180 | fset_selected_window (f, new_selected_window); | ||
| 5181 | } | 5165 | } |
| 5182 | else | ||
| 5183 | unblock_input (); | ||
| 5184 | 5166 | ||
| 5167 | unblock_input (); | ||
| 5185 | FRAME_WINDOW_CHANGE (f) = true; | 5168 | FRAME_WINDOW_CHANGE (f) = true; |
| 5186 | } | 5169 | } |
| 5187 | else | 5170 | else |