From: Martin Rudalics Date: Fri, 11 Oct 2024 08:39:10 +0000 (+0200) Subject: Fix how 'no-other-window' window parameter is ignored (Bug#73706) X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=3f32305281348d26d60bc2cc947e734a5a83f63e;p=emacs.git Fix how 'no-other-window' window parameter is ignored (Bug#73706) * lisp/window.el (window-no-other-p): New function. (window-in-direction, get-lru-window, get-mru-window) (get-largest-window, other-window, window-at-x-y) (delete-window-choose-selected, delete-window): Use it to check whether 'ignore-window-parameters' should inhibit processing the 'no-other-window' parameter (Bug#73706). * lisp/erc/erc-speedbar.el (erc-speedbar-toggle-nicknames-window-lock): Use 'window-no-other-p'. * doc/lispref/windows.texi (Windows and Frames) (Deleting Windows, Cyclic Window Ordering): Describe new function 'window-no-other-p' and use it in description of functions that call it. (Window Parameters): Add cross references for 'no-other-window' parameter. (cherry picked from commit 3462b2b9d0ca6a483d5c3200ef71a8ca243225d1) --- diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index d9e99d9ca5c..0b8d7d3b76d 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -427,13 +427,14 @@ window @var{window}. The argument @var{direction} must be one of argument @var{window} must denote a live window and defaults to the selected one. -This function does not return a window whose @code{no-other-window} -parameter is non-@code{nil} (@pxref{Window Parameters}). If the nearest -window's @code{no-other-window} parameter is non-@code{nil}, this -function tries to find another window in the indicated direction whose -@code{no-other-window} parameter is @code{nil}. If the optional -argument @var{ignore} is non-@code{nil}, a window may be returned even -if its @code{no-other-window} parameter is non-@code{nil}. +This function does not return a window for which +@code{window-no-other-p} (@pxref{Cyclic Window Ordering}) returns +non-@code{nil}. If the nearest window's @code{no-other-window} +parameter is non-@code{nil}, this function tries to find another window +in the indicated direction whose @code{no-other-window} parameter is +@code{nil}. However, if the optional argument @var{ignore} is +non-@code{nil}, a window may be returned even if its +@code{no-other-window} parameter is non-@code{nil}. If the optional argument @var{sign} is a negative number, it means to use the right or bottom edge of @var{window} as reference position @@ -1585,9 +1586,10 @@ choose the first window (the window returned by @code{frame-first-window}) on that frame. @end itemize -A window with a non-@code{nil} @code{no-other-window} parameter is -chosen only if all other windows on that frame have that parameter set -to a non-@code{nil} value too. +A window for which @code{window-no-other-p} (@pxref{Cyclic Window +Ordering}) returns non-@code{nil} is chosen only if all other windows on +that frame have their @code{no-other-window} parameter set to a +non-@code{nil} value too. @end defopt @deffn Command delete-other-windows &optional window @@ -2129,16 +2131,33 @@ The optional argument @var{all-frames} has the same meaning as in @code{next-window}, like a @code{nil} @var{minibuf} argument to @code{next-window}. -This function does not select a window that has a non-@code{nil} -@code{no-other-window} window parameter (@pxref{Window Parameters}), -provided that @code{ignore-window-parameters} is @code{nil}. - If the @code{other-window} parameter of the selected window is a function, and @code{ignore-window-parameters} is @code{nil}, that function will be called with the arguments @var{count} and @var{all-frames} instead of the normal operation of this function. + +Otherwise, this function does not select a window for which the function +@code{window-no-other-p} (see next) returns @code{nil}. @end deffn +@defun window-no-other-p &optional window +This function returns non-@code{nil} if @var{window} should not be used +as ``other'' window by commands like @code{other-window} or functions +like @code{get-lru-window} (see below). It's also called when deleting +the selected window (@pxref{Deleting Windows}) and a new selected window +has to be chosen. + +More precisely, this function returns non-@code{nil} if the +@code{no-other-window} parameter of @var{window} is non-@code{nil} and +@code{ignore-window-parameters} is @code{nil}. It returns @code{nil} in +any other case. + +Note that if this function returns @code{nil}, this does not necessarily +mean that @var{window} can be selected. A tooltip window (@pxref{Basic +Windows}), for example, has its @code{no-other-window} parameter set to +@code{t} by default but cannot be selected. +@end defun + @defun walk-windows fun &optional minibuf all-frames This function calls the function @var{fun} once for each live window, with the window as the argument. @@ -2186,8 +2205,9 @@ optional argument @var{dedicated} is non-@code{nil}. The selected window is never returned, unless it is the only candidate. However, if the optional argument @var{not-selected} is non-@code{nil}, this function returns @code{nil} in that case. The optional argument -@var{no-other}, if non-@code{nil}, means to never return a window whose -@code{no-other-window} parameter is non-@code{nil}. +@var{no-other}, if non-@code{nil}, means to never return a window for +which @code{window-no-other-p} (@pxref{Cyclic Window Ordering}) returns +non-@code{nil}. @end defun @cindex most recently used window @@ -6784,7 +6804,10 @@ This parameter affects the execution of @code{other-window} @item no-other-window @vindex no-other-window@r{, a window parameter} This parameter marks the window as not selectable by @code{other-window} -(@pxref{Cyclic Window Ordering}). +(@pxref{Cyclic Window Ordering}). It is by default @code{t} for tooltip +windows (@pxref{Basic Windows}). Use @code{window-no-other-p} +(@pxref{Cyclic Window Ordering}) to check whether it applies to a +specific window. @item clone-of @vindex clone-of@r{, a window parameter} diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el index e45fb9a7adf..a281e13734c 100644 --- a/lisp/erc/erc-speedbar.el +++ b/lisp/erc/erc-speedbar.el @@ -652,8 +652,7 @@ unlock the window." (when-let ((window (get-buffer-window speedbar-buffer))) (let ((val (cond ((natnump arg) t) ((integerp arg) nil) - (t (not (window-parameter window - 'no-other-window)))))) + (t (not (window-no-other-p window)))))) (with-current-buffer speedbar-buffer (setq cursor-type (not val))) (set-window-parameter window 'no-other-window val) diff --git a/lisp/window.el b/lisp/window.el index 68d599c0aa1..712a9ccae04 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -427,6 +427,16 @@ The functions currently affected by this are `split-window', An application may bind this to a non-nil value around calls to these functions to inhibit processing of window parameters.") +(defun window-no-other-p (&optional window) + "Return non-nil if WINDOW should not be used as \"other\" window. +WINDOW must be a live window and defaults to the selected one. + +Return non-nil if the `no-other-window' parameter of WINDOW is non-nil +and `ignore-window-parameters' is nil. Return nil in any other case." + (setq window (window-normalize-window window t)) + (and (not ignore-window-parameters) + (window-parameter window 'no-other-window))) + ;; This must go to C, finally (or get removed). (defconst window-safe-min-height 1 "The absolute minimum number of lines of any window. @@ -2248,11 +2258,11 @@ as seen from the position of `window-point' in window WINDOW. DIRECTION should be one of `above', `below', `left' or `right'. WINDOW must be a live window and defaults to the selected one. -Do not return a window whose `no-other-window' parameter is -non-nil. If the nearest window's `no-other-window' parameter is -non-nil, try to find another window in the indicated direction. -If, however, the optional argument IGNORE is non-nil, return that -window even if its `no-other-window' parameter is non-nil. +Do not return a window for which `window-no-other-p' returns non-nil. +If `window-no-other-p' returns non-nil for the nearest window, try to +find another window in the indicated direction. If, however, the +optional argument IGNORE is non-nil, return the nearest window even if +`window-no-other-p' returns for it a non-nil value. Optional argument SIGN a negative number means to use the right or bottom edge of WINDOW as reference position instead of @@ -2316,7 +2326,7 @@ Return nil if no suitable window can be found." (cond ((or (eq window w) ;; Ignore ourselves. - (and (window-parameter w 'no-other-window) + (and (window-no-other-p w) ;; Ignore W unless IGNORE is non-nil. (not ignore)))) (hor @@ -2432,14 +2442,13 @@ and no others." (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. Optional argument NO-OTHER non-nil means to -never return a window whose `no-other-window' parameter is -non-nil. +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. Optional +argument NO-OTHER non-nil means to never return a window for which +`window-no-other-p' returns non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2463,8 +2472,7 @@ selected frame and no others." (dolist (window windows) (when (and (or dedicated (not (window-dedicated-p window))) (or (not not-selected) (not (eq window (selected-window)))) - (or (not no-other) - (not (window-parameter window 'no-other-window)))) + (or (not no-other) (not (window-no-other-p window)))) (setq time (window-use-time window)) (if (or (eq window (selected-window)) (not (window-full-width-p window))) @@ -2478,12 +2486,11 @@ selected frame and no others." (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. Optional -argument NO-OTHER non-nil means to never return a window whose -`no-other-window' parameter is non-nil. +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. Optional argument NO-OTHER non-nil means to +never return a window for which `window-no-other-p' returns non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2505,8 +2512,7 @@ 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 no-other) - (not (window-parameter window 'no-other-window))) + (or (not no-other) (not (window-no-other-p window))) (or (not best-time) (> time best-time))) (setq best-time time) (setq best-window window))) @@ -2514,12 +2520,11 @@ selected frame and no others." (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. Optional -argument NO-OTHER non-nil means to never return a window whose -`no-other-window' parameter is non-nil. +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. Optional argument NO-OTHER non-nil means to +never return a window for which `window-no-other-p' returns non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2543,8 +2548,7 @@ selected frame and no others." (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 no-other) - (not (window-parameter window 'no-other-window)))) + (or (not no-other) (window-no-other-p window))) (setq size (* (window-pixel-height window) (window-pixel-width window))) (when (> size best-size) @@ -3904,12 +3908,10 @@ skip -COUNT windows backwards. COUNT zero means do not skip any window, so select the selected window. In an interactive call, COUNT is the numeric prefix argument. Return nil. -If the `other-window' parameter of the selected window is a -function and `ignore-window-parameters' is nil, call that -function with the arguments COUNT and ALL-FRAMES. - -This function does not select a window whose `no-other-window' -window parameter is non-nil. +If the `other-window' parameter of the selected window is a function and +`ignore-window-parameters' is nil, call that function with the arguments +COUNT and ALL-FRAMES. Otherwise, do not return a window for which +`window-no-other-p' returns non-nil. This function uses `next-window' for finding the window to select. The argument ALL-FRAMES has the same meaning as in @@ -3935,7 +3937,7 @@ always effectively nil." ;; Keep out of infinite loops. When COUNT has not changed ;; since we last looked at `window' we're probably in one. (throw 'exit nil))) - ((window-parameter window 'no-other-window) + ((window-no-other-p window) (unless old-window ;; The first non-selectable window `next-window' got us: ;; Remember it and the current value of COUNT. @@ -3951,7 +3953,7 @@ always effectively nil." ;; Keep out of infinite loops. When COUNT has not changed ;; since we last looked at `window' we're probably in one. (throw 'exit nil))) - ((window-parameter window 'no-other-window) + ((window-no-other-p window) (unless old-window ;; The first non-selectable window `previous-window' got ;; us: Remember it and the current value of COUNT. @@ -4124,10 +4126,10 @@ Tool-bar and tab-bar pseudo-windows are ignored by this function: if the specified coordinates are in any of these two windows, this function returns nil. -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." +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 +`window-no-other-p' returns non-nil for the window located at the +specified coordinates." (setq frame (window-normalize-frame frame)) (let* ((root-edges (window-edges (frame-root-window frame) nil nil t)) (root-left (nth 2 root-edges)) @@ -4140,7 +4142,7 @@ a non-nil `no-other-window' parameter." (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)) + (if (and no-other (window-no-other-p window)) (throw 'window nil) (throw 'window window))))) frame)))) @@ -4152,13 +4154,13 @@ another live window on that frame to serve as its selected window. This option controls the window that is selected in such a situation. -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." +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 for which +`window-no-other-p' returns non-nil is chosen only if all windows on +that frame have their `no-other-window' 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)) @@ -4281,15 +4283,14 @@ the option `delete-window-choose-selected'." (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) + ((and (window-no-other-p (frame-selected-window frame)) ;; 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) + (unless (window-no-other-p other) (set-frame-selected-window frame other) (throw 'found t))) frame))))