Subject: bug#32790: 27.0.50; point jumps unexpectedly after delete-window

From: Juri Linkov <[email-masked]>
Date: Tue, 13 Nov 2018 01:24:53 +0200

>> This summarizes the prefix keys where 'default' is the default
>> window selection behavior, and 'window-noselect' restores a previously
>> selected window:
>>
>>                                      default     window-noselect
>> relative to the position of point   no prefix   M-0
>> relative to the first edge          M-1         C-u
>> relative to the last edge           M-- 1       M--
>
> I would drop that edge thingy, interactively.  I'm quite convinced
> that nobody would ever use it.
>
> IMHO this "relative" code is there for historical reasons - the author
> wrote the simpler edges versions first, wrote the point version later
> and didn't want to drop the edges versions then (maybe also because he
> wasn't sure whether the point version would always work).  What I
> doubt is that a user would ever make the relativity choice
> interactively.  Rather people would be used to one or the other.

I agree, it's too complicated, I never used edges in windmove-do-window-select.

>> But maybe also another choice 'window-select' should be added to
>> force window selection?  I mean that some commands don't select
>> the displayed window by default, e.g. help commands like
>> 'C-h e', 'C-h f', 'C-h v', 'C-h k' after their invocation
>> don't select the window with the *Help* buffer.
>
> With 'help-window-select' non-nil they should always select the help
> window.

This means that every package should provide own customization
for the select/no-select choice for its windows, instead of
a general solution like inhibit-window-select that I tried to do.

>> Or maybe a prefix key should invert the default behavior,
>> e.g. 'S-M-right C-x v =' by default selects the displayed window,
>> so ‘C-u S-M-right C-x v =’ will not select the window.
>> 'S-M-right C-h e' by default doesn't select the window,
>> so ‘C-u S-M-right C-h e’ will select the window.
>
> That would confuse the hell out of me.  I'm not sure how you or others
> feel, but personally I would prefer a fixed two layer choice like:
>
> (1) The select/no-select choice always bound to one and the same
> prefix key _regardless_ of the default behavior of the function (for
> the buffer at hand), and

This is implemented in a new version:

(defun windmove-display-in-direction (dir &optional arg)
  "Display the next buffer in the window at direction DIR.
Create a new window if there is no window in that direction.
Without a prefix arg, select the window with a displayed buffer.
If prefix ARG is `C-u', reselect a previously selected window."
  (interactive)
  (let* ((no-select (consp arg))
         (old-window (or (minibuffer-selected-window) (selected-window)))
         (new-window)
         (minibuffer-depth (minibuffer-depth))
         (action display-buffer-overriding-action)
         (command this-command)
         (clearfun (make-symbol "clear-display-buffer-overriding-action"))
         (exitfun
          (lambda ()
            (setq display-buffer-overriding-action action)
            (when (window-live-p (if no-select old-window new-window))
              (select-window (if no-select old-window new-window)))
            (remove-hook 'post-command-hook clearfun))))
    (fset clearfun
          (lambda ()
            (unless (or
		     ;; Remove the hook immediately
		     ;; after exiting the minibuffer.
		     (> (minibuffer-depth) minibuffer-depth)
		     ;; But don't remove immediately after
		     ;; adding the hook by the same command below.
		     (eq this-command command))
              (funcall exitfun))))
    (add-hook 'post-command-hook clearfun)
    (push (lambda (buffer alist)
	    (unless (> (minibuffer-depth) minibuffer-depth)
	      (let ((window (if (eq dir 'same-window)
			        (selected-window)
                              (window-in-direction
                               dir nil nil
                               (and arg (prefix-numeric-value arg))
                               windmove-wrap-around)))
                    (type 'reuse))
                (unless window
                  (setq window (split-window nil nil dir) type 'window))
		(setq new-window (window--display-buffer buffer window type alist)))))
          display-buffer-overriding-action)
    (message "[display-%s]" dir)))

> (2) in addition to a window relative to the selected window (above, on
> the right, ... a new one always made by splitting the selected window)
> optionally allow a window relative to the selected frame (on the top
> full-width, on the right full-height, ... a new one always made by
> splitting the frame's root window) bound to another prefix key.
>
> Then (2) could be generalized via a global option to use/make a new
> (child) frame in the indicated direction or whatever people want.

But does windmove support frames in the first place?
Can you use e.g. S-left to select a frame on the left?
Does window-in-direction currently return frames?