mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2026-09-10 07:46:51 -04:00
Fix issues related to window layout changes (Bug#81406)
* src/window.c (Vwindow_combination_resize): In doc-string say that binding this to nil may be necessary to produce specific, predefined frame layouts (Bug#81406). * lisp/window-x.el (window-layout-rotate-clockwise) (window-layout-rotate-anticlockwise) (window-layout-flip-leftright, window-layout-flip-topdown) (window-layout-transpose, rotate-windows-change-selected) (rotate-windows, rotate-windows-back): Rewrite doc-strings. Make sure that non-interactive calls with nil or absent WINDOW argument work on the frame's main window. Fix infinite loop when 'rotate-windows' is called for a non-selected frame. * doc/lispref/windows.texi (Recombining Windows): Say that binding 'window-combination-resize' to nil may be necessary to produce specific, predefined frame layouts (Bug#81406). (Changing Window Layouts): Minor rewrite. * etc/NEWS: Announce names of new commands to change window layout (Bug#81406).
This commit is contained in:
parent
86b65d82c7
commit
4be321d511
|
|
@ -2025,6 +2025,13 @@ combination.
|
|||
The default is @code{nil}. Other values are reserved for future use. A
|
||||
specific split operation may ignore the value of this variable if it is
|
||||
affected by a non-@code{nil} value of @code{window-combination-limit}.
|
||||
|
||||
If you plan to use a sequence of @code{split-window} calls to produce a
|
||||
specific, predefined layout of windows on a frame, bind this variable
|
||||
temporarily to nil. @code{window-state-put} (@pxref{Window
|
||||
Configurations}) and the functions to change window layouts
|
||||
(@pxref{Changing Window Layouts}) do that in order to restore a previous
|
||||
or systematically changed layout of a frame.
|
||||
@end defopt
|
||||
|
||||
To illustrate the effect of @code{window-combination-resize}, consider
|
||||
|
|
@ -2302,8 +2309,8 @@ below, we shall always assume that the windows displayed constitute
|
|||
their frame's main window and the @var{window} argument is @code{nil}
|
||||
unless stated otherwise.
|
||||
|
||||
The first two commands rotate a window layout either clockwise or
|
||||
counterclockwise.
|
||||
The first two commands rotate an entire window layout either
|
||||
clockwise or counterclockwise.
|
||||
@cindex rotate window layout
|
||||
|
||||
@deffn Command window-layout-rotate-clockwise &optional window
|
||||
|
|
@ -2368,7 +2375,7 @@ windows on the top and vice-versa as in the example below.
|
|||
|
||||
@deffn Command window-layout-flip-leftright &optional window
|
||||
This command rearranges window in a way that the windows on the right
|
||||
become the window on the left, and vice-versa.
|
||||
become the windows on the left, and vice-versa.
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
|
|
@ -2409,13 +2416,19 @@ becomes a vertical split and vice versa.
|
|||
The final two commands can be used to rotate windows within the existing
|
||||
layout. They are like the commands that rotate the layout but leave the
|
||||
underlying structure of the layout unchanged. What actually changes are
|
||||
the positions of windows within the existing layout.
|
||||
the positions of windows within the existing layout. This happens in a
|
||||
way that the space formerly occupied by any window will be occupied by
|
||||
the window preceding (following if @var{reverse} is non-nil) it in the
|
||||
cyclic ordering of windows (@pxref{Cyclic Window Ordering}) on
|
||||
@var{window}'s frame. These commands may signal an error if windows
|
||||
chosen to rotate are dedicated to their buffers, atomic or of fixed
|
||||
size.
|
||||
@cindex rotating windows
|
||||
|
||||
@deffn Command rotate-windows &optional window reverse
|
||||
This rotate windows under @var{window} in cyclic ordering. The optional
|
||||
argument @var{reverse} means to rotate windows backward, in reverse
|
||||
cyclic order.
|
||||
This command rotates @var{window}'c child windows in cyclic ordering.
|
||||
The optional argument @var{reverse} means to rotate windows backwards,
|
||||
in reverse cyclic order.
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
|
|
@ -2432,7 +2445,7 @@ cyclic order.
|
|||
@end deffn
|
||||
|
||||
@deffn Command rotate-windows-back &optional window
|
||||
This command rotates windows under @var{window} backward in cyclic
|
||||
This command rotates @var{window}'s child windows backwards in cyclic
|
||||
ordering.
|
||||
|
||||
@smallexample
|
||||
|
|
@ -2455,7 +2468,7 @@ The last two commands are subject to the following option.
|
|||
If this is @code{nil}, the selected window will remain unaffected by
|
||||
@code{rotate-windows} and @code{rotate-windows-back}. Otherwise, the
|
||||
selected window will change to the window that appears at the location
|
||||
of the selected window before any of these commands were invoked.
|
||||
of the window selected before any of these commands were invoked.
|
||||
@end defopt
|
||||
|
||||
|
||||
|
|
|
|||
17
etc/NEWS
17
etc/NEWS
|
|
@ -357,14 +357,15 @@ increments as with Emacs 24 through Emacs 30 you now have to set
|
|||
** Windows
|
||||
|
||||
+++
|
||||
*** New commands to modify window layouts.
|
||||
|
||||
- 'C-x w t' and 'C-x w r <left>/<right>' rotate the window layout.
|
||||
- 'C-x w o <left>/<right>' rotate the windows within the current layout.
|
||||
- 'C-x w f <left>/<right>/<up>/<down>' flip window layouts.
|
||||
|
||||
By default, these commands operate on the selected frame's root window.
|
||||
With a prefix argument, they operate on the selected window's parent.
|
||||
*** New commands to modify window layouts of frames.
|
||||
'window-layout-rotate-clockwise' and its counterpart
|
||||
'window-layout-rotate-anticlockwise' rotate an entire window layout.
|
||||
'window-layout-flip-topdown' and 'window-layout-flip-leftright' flip the
|
||||
window layout vertically and horizontally.
|
||||
'window-layout-transpose' reorganizes windows such that every horizontal
|
||||
split becomes a vertical split and vice versa.
|
||||
'rotate-windows' and its counterpart 'rotate-windows-back' rotate
|
||||
windows in cylic ordering.
|
||||
|
||||
+++
|
||||
*** Windmove commands now move to skipped windows if invoked twice in a row.
|
||||
|
|
|
|||
179
lisp/window-x.el
179
lisp/window-x.el
|
|
@ -29,17 +29,8 @@
|
|||
|
||||
;;; Code:
|
||||
|
||||
(defcustom rotate-windows-change-selected t
|
||||
"If nil the selected window will not change with `rotate-windows'.
|
||||
|
||||
The selected window before and after the function call will stay
|
||||
unchanged if nil. `rotate-windows-back' is also affected."
|
||||
:type 'boolean
|
||||
:group 'windows)
|
||||
|
||||
(defun window-tree-normal-sizes (window &optional next)
|
||||
"Return normal sizes of all windows rooted at WINDOW.
|
||||
|
||||
The return value is a list of the form (SPLIT-TYPE PARENT-WIN
|
||||
PARENT-WIN-HEIGHT PARENT-WIN-WIDTH . WS), where SPLIT-TYPE is non-nil if
|
||||
PARENT-WIN is split horizontally; PARENT-WIN is the internal window;
|
||||
|
|
@ -47,7 +38,7 @@ PARENT-WIN-HEIGHT and PARENT-WIN-WIDTH are the normal heights of
|
|||
PARENT-WIN; and WS is a list of lists the form (WINDOW HEIGHT WIDTH)
|
||||
where HEIGHT and WIDTH are the normal height and width of the window.
|
||||
|
||||
(fn WINDOW)"
|
||||
\(fn WINDOW)"
|
||||
(let (list)
|
||||
(while window
|
||||
(setq list
|
||||
|
|
@ -77,97 +68,112 @@ where HEIGHT and WIDTH are the normal height and width of the window.
|
|||
(if current-prefix-arg (window-parent) (window-main-window)))
|
||||
|
||||
;;;###autoload
|
||||
(defun window-layout-rotate-anticlockwise (&optional window)
|
||||
"Rotate window layout of WINDOW counterclockwise by 90 degrees.
|
||||
(defun window-layout-rotate-clockwise (&optional window)
|
||||
"Clockwise rotate layout of WINDOW's child windows.
|
||||
WINDOW must be a parent window and defaults to the main window of the
|
||||
selected frame. Interactively, with a prefix argument, rotate clockwise
|
||||
the layout of the child windows of the selected window's parent. Signal
|
||||
an error if WINDOW is not a parent window
|
||||
|
||||
If WINDOW is nil, it defaults to the root window of the selected frame.
|
||||
|
||||
Interactively, a prefix argument says to rotate the parent window of the
|
||||
selected window."
|
||||
Recursively rotate the entire layout of WINDOW's child windows clockwise
|
||||
by 90 degrees. Do not change the selected window of WINDOW's frame. If
|
||||
you want to rotate windows within their frame's layout, consider using
|
||||
`rotate-windows' instead."
|
||||
(interactive (list (window--rotate-interactive-arg)))
|
||||
(window--transpose window '(right . above) nil))
|
||||
(window--transpose (or window (window-main-window)) '(left . below) nil))
|
||||
|
||||
;;;###autoload
|
||||
(defun window-layout-rotate-clockwise (&optional window)
|
||||
"Rotate window layout under WINDOW clockwise by 90 degrees.
|
||||
(defun window-layout-rotate-anticlockwise (&optional window)
|
||||
"Rotate layout of WINDOW's child windows counterclockwise by 90 degrees.
|
||||
WINDOW must be a parent window and defaults to the main window of the
|
||||
selected frame. Interactively, with a prefix argument, rotate
|
||||
counterclockwise the layout of the child windows of the selected
|
||||
window's parent. Signal an error if WINDOW is not a parent window
|
||||
|
||||
If WINDOW is nil, it defaults to the root window of the selected frame.
|
||||
|
||||
Interactively, a prefix argument says to rotate the parent window of the
|
||||
selected window."
|
||||
Recursively rotate the entire layout of WINDOW's child windows
|
||||
counterclockwise by 90 degrees. Do not change the selected window of
|
||||
WINDOW's frame. If you want to rotate windows within their frame's
|
||||
layout, consider using `rotate-windows-back' instead."
|
||||
(interactive (list (window--rotate-interactive-arg)))
|
||||
(window--transpose window '(left . below) nil))
|
||||
(window--transpose (or window (window-main-window)) '(right . above) nil))
|
||||
|
||||
;;;###autoload
|
||||
(defun window-layout-flip-leftright (&optional window)
|
||||
"Horizontally flip windows under WINDOW.
|
||||
"Horizontally flip WINDOW's child windows.
|
||||
WINDOW must be a parent window and defaults to the main window of the
|
||||
selected frame. Interactively, with a prefix argument, flip
|
||||
horizontally the layout of the child windows of the selected window's
|
||||
parent. Signal an error if WINDOW is not a parent window
|
||||
|
||||
Flip the window layout so that the window on the right becomes the
|
||||
window on the left, and vice-versa.
|
||||
|
||||
If WINDOW is nil, it defaults to the root window of the selected frame.
|
||||
|
||||
Interactively, a prefix argument says to flip the parent window of the
|
||||
selected window."
|
||||
Recursively flip the layout of WINDOW's child windows so that a child
|
||||
window on the right becomes a child window on the left and vice-versa."
|
||||
(interactive (list (window--rotate-interactive-arg)))
|
||||
(window--transpose window '(below . left) t))
|
||||
(window--transpose (or window (window-main-window)) '(below . left) t))
|
||||
|
||||
;;;###autoload
|
||||
(defun window-layout-flip-topdown (&optional window)
|
||||
"Vertically flip windows under WINDOW.
|
||||
"Vertically flip WINDOW's child windows.
|
||||
WINDOW must be a parent window and defaults to the main window of the
|
||||
selected frame. Interactively, with a prefix argument, flip vertically
|
||||
the layout of the child windows of the selected window's parent. Signal
|
||||
an error if WINDOW is not a parent window
|
||||
|
||||
Flip the window layout so that the top window becomes the bottom window,
|
||||
and vice-versa.
|
||||
|
||||
If WINDOW is nil, it defaults to the root window of the selected frame.
|
||||
|
||||
Interactively, a prefix argument says to flip the parent window of the
|
||||
selected window."
|
||||
Recursively flip the layout of WINDOW's child windows so that a child
|
||||
window on the top becomes a child window on the bottom and vice-versa."
|
||||
(interactive (list (window--rotate-interactive-arg)))
|
||||
(window--transpose window '(above . right) t))
|
||||
(window--transpose (or window (window-main-window)) '(above . right) t))
|
||||
|
||||
;;;###autoload
|
||||
(defun window-layout-transpose (&optional window)
|
||||
"Transpose windows under WINDOW.
|
||||
"Transpose child windows of WINDOW.
|
||||
WINDOW must be a parent window and defaults to the main window of the
|
||||
selected frame. Interactively, with a prefix argument, transpose the
|
||||
layout of the child windows of the selected window's parent. Signal an
|
||||
error if WINDOW is not a parent window
|
||||
|
||||
Reorganize the windows under WINDOW so that every horizontal split
|
||||
becomes a vertical split, and vice versa. This is equivalent to
|
||||
diagonally flipping.
|
||||
|
||||
If WINDOW is nil, it defaults to the root window of the selected frame.
|
||||
|
||||
Interactively, a prefix argument says to transpose the parent window of
|
||||
the selected window."
|
||||
Recursively reorganize WINDOW's child windows so that each horizontal
|
||||
split becomes a vertical split and vice versa."
|
||||
(interactive (list (window--rotate-interactive-arg)))
|
||||
(window--transpose window '(right . below) nil))
|
||||
(window--transpose (or window (window-main-window)) '(right . below) nil))
|
||||
|
||||
;;;###autoload
|
||||
(defun rotate-windows-back (&optional window)
|
||||
"Rotate windows under WINDOW backward in cyclic ordering.
|
||||
|
||||
If WINDOW is nil, it defaults to the root window of the selected frame.
|
||||
|
||||
Interactively, a prefix argument says to rotate the parent window of the
|
||||
selected window."
|
||||
(interactive (list (window--rotate-interactive-arg)))
|
||||
(rotate-windows window t))
|
||||
(defcustom rotate-windows-change-selected t
|
||||
"Whether rotating windows will change the selected window.
|
||||
If this is nil, `rotate-windows' and `rotate-windows-back' do not change
|
||||
a frame's selected window. Otherwise, the new selected window will be
|
||||
the window that appears at the location of the previously selected
|
||||
window."
|
||||
:type 'boolean
|
||||
:group 'windows)
|
||||
|
||||
;;;###autoload
|
||||
(defun rotate-windows (&optional window reverse)
|
||||
"Rotate windows under WINDOW in cyclic ordering.
|
||||
"Rotate child windows of WINDOW in cyclic ordering.
|
||||
WINDOW must be a parent window and defaults to the main window of the
|
||||
selected frame. Interactively, with a prefix argument, rotate the child
|
||||
windows of the selected window's parent.
|
||||
|
||||
Optional argument REVERSE says to rotate windows backward, in reverse
|
||||
cyclic order.
|
||||
Optional argument REVERSE non-nil means to rotate windows backwards, in
|
||||
reverse cyclic order. Signal an error if WINDOW is not a parent window,
|
||||
all descendants of WINDOW are dedicated or some windows are of fixed
|
||||
size or atomic.
|
||||
|
||||
If WINDOW is nil, it defaults to the root window of the selected frame.
|
||||
Rotating windows leaves the way a frame layout has been produced via
|
||||
splitting and deleting windows unaltered. It only \"moves\" windows
|
||||
within that layout such that the space formerly occupied by any window
|
||||
is now occupied by the window preceding (following if REVERSE is
|
||||
non-nil) it in that order.
|
||||
|
||||
Interactively, a prefix argument says to rotate the parent window of the
|
||||
selected window."
|
||||
If you want to rotate the entire layout of windows consider using the
|
||||
function `window-layout-rotate-clockwise' instead."
|
||||
(interactive (list (window--rotate-interactive-arg)))
|
||||
(when (or (not window) (window-live-p window))
|
||||
(setq window (or window (window-main-window)))
|
||||
(when (window-live-p window)
|
||||
(user-error "No windows to rotate"))
|
||||
(let* ((frame (window-frame window))
|
||||
(selected-window (frame-selected-window window))
|
||||
(x-y (and rotate-windows-change-selected
|
||||
(cons (1+ (window-pixel-left selected-window))
|
||||
(1+ (window-pixel-top selected-window)))))
|
||||
(win-tree (car (window-tree-normal-sizes window)))
|
||||
(winls (or
|
||||
(seq-filter
|
||||
|
|
@ -175,11 +181,12 @@ selected window."
|
|||
(and (window-live-p win)
|
||||
(not (window-dedicated-p win))))
|
||||
(flatten-list win-tree))
|
||||
;; Do we really care - the window/buffer relationship
|
||||
;; should not be affected by rotating.
|
||||
(user-error "All windows are dedicated")))
|
||||
(rotated-ls (if reverse
|
||||
(append (cdr winls) (list (car winls)))
|
||||
(append (last winls) winls)))
|
||||
(other-window-arg (if reverse 1 -1))
|
||||
(first-window (car rotated-ls))
|
||||
(new-win-tree
|
||||
;; Recursively process `win-tree' and construct a new tree
|
||||
|
|
@ -193,14 +200,31 @@ selected window."
|
|||
(t tree)))))
|
||||
(when (or (seq-some #'window-atom-root winls)
|
||||
(seq-some #'window-fixed-size-p winls))
|
||||
(user-error "Cannot rotate windows due to fixed size or atom windows"))
|
||||
(user-error "Cannot rotate windows due to fixed size or atomic windows"))
|
||||
(delete-other-windows-internal first-window window)
|
||||
(window--transpose-1 new-win-tree first-window '(below . right) t nil)
|
||||
(set-frame-selected-window frame selected-window)
|
||||
(when rotate-windows-change-selected
|
||||
(other-window other-window-arg)
|
||||
(while (not (memq (selected-window) winls))
|
||||
(other-window other-window-arg)))))
|
||||
(when x-y
|
||||
;; Try to select the window at the position previously occupied by
|
||||
;; the selected window.
|
||||
(let ((window-at-x-y (window-at-x-y (car x-y) (cdr x-y) frame t)))
|
||||
(when window-at-x-y
|
||||
(setq selected-window window-at-x-y))))
|
||||
|
||||
(set-frame-selected-window frame selected-window)))
|
||||
|
||||
;;;###autoload
|
||||
(defun rotate-windows-back (&optional window)
|
||||
"Rotate child windows of WINDOW backwards in cyclic ordering.
|
||||
WINDOW must be a parent window and defaults to the main window of the
|
||||
selected frame. Interactively, with a prefix argument, rotate backwards
|
||||
the child windows of the selected window's parent. Signal an error if
|
||||
WINDOW is not a parent window, all descendants of WINDOW are dedicated
|
||||
or some of them are of fixed size or atomic.
|
||||
|
||||
If you want to rotate the entire layout of windows, consider using the
|
||||
function `window-layout-rotate-anticlockwise' instead."
|
||||
(interactive (list (window--rotate-interactive-arg)))
|
||||
(rotate-windows window t))
|
||||
|
||||
(defun window--transpose (window conf no-resize)
|
||||
"Rearrange windows under WINDOW recursively.
|
||||
|
|
@ -424,8 +448,7 @@ absolute value of ARG. Return the new frame."
|
|||
(let ((comb (window-get-split-combination main arg)))
|
||||
(window-state-put (window-state-get comb)
|
||||
(window-main-window (make-frame)))
|
||||
(delete-window comb))
|
||||
))))
|
||||
(delete-window comb))))))
|
||||
|
||||
(provide 'window-x)
|
||||
;;; window-x.el ends here
|
||||
|
|
|
|||
|
|
@ -9454,7 +9454,10 @@ windows in the same combination.
|
|||
Other values are reserved for future use.
|
||||
|
||||
A specific split operation may ignore the value of this variable if it
|
||||
is affected by a non-nil value of `window-combination-limit'. */);
|
||||
is affected by a non-nil value of `window-combination-limit'. If you
|
||||
want to use a sequence of `split-window' calls to produce a specific,
|
||||
predefined layout of windows on a frame, bind this variable temporarily
|
||||
to nil. */);
|
||||
Vwindow_combination_resize = Qnil;
|
||||
|
||||
DEFVAR_LISP ("window-combination-limit", Vwindow_combination_limit,
|
||||
|
|
|
|||
Loading…
Reference in a new issue