diff options
| author | Martin Rudalics | 2016-10-05 10:28:36 +0200 |
|---|---|---|
| committer | Martin Rudalics | 2016-10-05 10:28:36 +0200 |
| commit | b8fd71d5709650c1aced92c772f70595c51881d2 (patch) | |
| tree | c40e7b3a63e7168d5bb337d5d19a9643fe1901f9 | |
| parent | 13ba5af7427bdbd022a9d449dc2987d6a96591eb (diff) | |
| download | emacs-b8fd71d5709650c1aced92c772f70595c51881d2.tar.gz emacs-b8fd71d5709650c1aced92c772f70595c51881d2.zip | |
Document and fix some bugs with side windows
Add a documentation for side windows and fix some bugs
found when testing their behavior. Also add a new window
parameter `no-delete-other-window', a new `display-buffer'
alist member called `window-parameters', and functions to
toggle and reverse side windows on a frame. Add new function
`window-swap-states' to exchange states of two live windows.
* lisp/window.el (display-buffer-in-atom-window): Use
`split-window-no-error'.
(window-sides-vertical): Maybe change layouts when setting this
variable.
(window-sides-reversed): New option.
(window-sides-slots): Rewrite doc-string and help echoes.
(window-sides-shown): New buffer-local variable set when showing
a buffer in a side window.
(window--sides-inhibit-check): New variable.
(window--sides-reverse-on-frame-p, window-toggle-side-windows)
(window--sides-reverse-all, window--sides-reverse-frame)
(window--sides-reverse-side, window--sides-reverse)
(window--sides-verticalize-frame, window--sides-verticalize)
(window--sides-check-failed): New functions.
(window--side-window-p): Remove function.
(window--major-non-side-window): Rename to `window-main-window',
adjust callers, rewrite doc-string.
(window--major-side-window): Rename to
`window--make-major-side-window-next-to', adjust caller, fix
doc-string.
(display-buffer-in-major-side-window): Rename to
`window--make-major-side-window', adjust
caller, rewrite doc-string. Make `window-side' and
`window-slot' parameters persistent (Bug#23858). Don't set
`delete-window' parameter. Add `preserve-size' entry to ALIST.
(delete-side-window): Remove function.
(display-buffer-in-side-window): Fix doc-string. Don't set
`delete-window' parameter. Add `preserve-size' entry to ALIST.
(window--side-check): Rename to window--sides-check. Rewrite
completely. Adjust caller.
(window-resize-no-error): Don't describe PIXELWISE argument.
(adjust-window-trailing-edge): Fix bug that disallowed
re-enlarging windows that were too small.
(window-deletable-p): Don't tell that a minibuffer window on a
non-minibuffer-only frame can be deleted. Fix doc-string.
(delete-window): Handle deleting a side window here (the
`delete-window' parameter is no more set for side windows).
(delete-other-windows): Handle ‘no-delete-other-window'
parameter. Don't treat side windows separately (see discussion
of Bug#24368) but keep optimization that makes the main window
the root window of its frame.
(switch-to-prev-buffer, switch-to-next-buffer): Handle side
windows and buffers shown in side windows separately.
(split-window-no-error): New function.
(window--state-get-1): Use right buffer when storing window
point and start positions and WRITABLE is nil (Bug#24368).
(window--state-put-1): Fix handling of `window-combination-limit'.
Use `split-window-no-error'.
(window--state-put-2): Try to restore windows with preserved
size to their original size. Fix bug where a fixed window's width
was not preserved.
(window-state-put): When reducing an internal window to a live
one, don't choose a side window.
(window-swap-states): New function.
(window-splittable-p): Don't call `window--side-window-p'.
(window--display-buffer): Handle `window-parameters' ALIST entry.
Minor rewrite.
(display-buffer): Mention `window-parameters' entry in
doc-string.
(display-buffer-at-bottom): Call `split-window-no-error'.
* doc/lispref/elisp.texi (Top): New section "Side Windows".
* doc/lispref/windows.texi (Deleting Windows): Fix descriptions
of `delete-window' and `delete-other-windows' wrt window
parameters and side windows.
(Display Action Functions): Mention `window-parameters' ALIST
entry.
(Side Windows): New section (Bug#18170).
(Window Configurations): Describe new function `window-swap-states'.
(Window Parameters): Say that functions may behave specially when
their homonymous window parameter has been set. Mention new
parameter `no-delete-other-window'. Add cross reference for
`window-side' and `window-slot' parameters.
| -rw-r--r-- | doc/lispref/elisp.texi | 9 | ||||
| -rw-r--r-- | doc/lispref/windows.texi | 394 | ||||
| -rw-r--r-- | etc/NEWS | 21 | ||||
| -rw-r--r-- | lisp/window.el | 906 |
4 files changed, 1012 insertions, 318 deletions
diff --git a/doc/lispref/elisp.texi b/doc/lispref/elisp.texi index 3297e5308ae..1c6e05901c1 100644 --- a/doc/lispref/elisp.texi +++ b/doc/lispref/elisp.texi | |||
| @@ -1038,6 +1038,7 @@ Windows | |||
| 1038 | a specific window. | 1038 | a specific window. |
| 1039 | * Quitting Windows:: How to restore the state prior to displaying a | 1039 | * Quitting Windows:: How to restore the state prior to displaying a |
| 1040 | buffer. | 1040 | buffer. |
| 1041 | * Side Windows:: Special windows on a frame's sides. | ||
| 1041 | * Window Point:: Each window has its own location of point. | 1042 | * Window Point:: Each window has its own location of point. |
| 1042 | * Window Start and End:: Buffer positions indicating which text is | 1043 | * Window Start and End:: Buffer positions indicating which text is |
| 1043 | on-screen in a window. | 1044 | on-screen in a window. |
| @@ -1051,6 +1052,14 @@ Windows | |||
| 1051 | redisplay going past a certain point, | 1052 | redisplay going past a certain point, |
| 1052 | or window configuration changes. | 1053 | or window configuration changes. |
| 1053 | 1054 | ||
| 1055 | Side Windows | ||
| 1056 | |||
| 1057 | * Displaying Buffers in Side Windows:: An action function for displaying | ||
| 1058 | buffers in side windows. | ||
| 1059 | * Side Window Options and Functions:: Further tuning of side windows. | ||
| 1060 | * Frame Layouts with Side Windows:: Setting up frame layouts with side | ||
| 1061 | windows. | ||
| 1062 | |||
| 1054 | Frames | 1063 | Frames |
| 1055 | 1064 | ||
| 1056 | * Creating Frames:: Creating additional frames. | 1065 | * Creating Frames:: Creating additional frames. |
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 3c9df0b306d..3ab8c952af8 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi | |||
| @@ -33,6 +33,7 @@ is displayed in windows. | |||
| 33 | a specific window. | 33 | a specific window. |
| 34 | * Quitting Windows:: How to restore the state prior to displaying a | 34 | * Quitting Windows:: How to restore the state prior to displaying a |
| 35 | buffer. | 35 | buffer. |
| 36 | * Side Windows:: Special windows on a frame's sides. | ||
| 36 | * Window Point:: Each window has its own location of point. | 37 | * Window Point:: Each window has its own location of point. |
| 37 | * Window Start and End:: Buffer positions indicating which text is | 38 | * Window Start and End:: Buffer positions indicating which text is |
| 38 | on-screen in a window. | 39 | on-screen in a window. |
| @@ -1275,9 +1276,12 @@ Configurations}). | |||
| 1275 | @deffn Command delete-window &optional window | 1276 | @deffn Command delete-window &optional window |
| 1276 | This function removes @var{window} from display and returns | 1277 | This function removes @var{window} from display and returns |
| 1277 | @code{nil}. If @var{window} is omitted or @code{nil}, it defaults to | 1278 | @code{nil}. If @var{window} is omitted or @code{nil}, it defaults to |
| 1278 | the selected window. If deleting the window would leave no more | 1279 | the selected window. |
| 1279 | windows in the window tree (e.g., if it is the only live window in the | 1280 | |
| 1280 | frame), an error is signaled. | 1281 | If deleting the window would leave no more windows in the window tree |
| 1282 | (e.g., if it is the only live window in the frame) or all remaining | ||
| 1283 | windows on @var{window}'s frame are side windows (@pxref{Side Windows}), | ||
| 1284 | an error is signaled. | ||
| 1281 | 1285 | ||
| 1282 | By default, the space taken up by @var{window} is given to one of its | 1286 | By default, the space taken up by @var{window} is given to one of its |
| 1283 | adjacent sibling windows, if any. However, if the variable | 1287 | adjacent sibling windows, if any. However, if the variable |
| @@ -1285,33 +1289,34 @@ adjacent sibling windows, if any. However, if the variable | |||
| 1285 | proportionally distributed among any remaining windows in the same | 1289 | proportionally distributed among any remaining windows in the same |
| 1286 | window combination. @xref{Recombining Windows}. | 1290 | window combination. @xref{Recombining Windows}. |
| 1287 | 1291 | ||
| 1288 | The behavior of this function may be altered by the window parameters | 1292 | The behavior of this function may be altered by the window parameters of |
| 1289 | of @var{window}, so long as the variable | 1293 | @var{window}, so long as the variable @code{ignore-window-parameters} is |
| 1290 | @code{ignore-window-parameters} is @code{nil}. If the value of | 1294 | @code{nil}. If the value of the @code{delete-window} window parameter |
| 1291 | the @code{delete-window} window parameter is @code{t}, this function | 1295 | is @code{t}, this function ignores all other window parameters. |
| 1292 | ignores all other window parameters. Otherwise, if the value of the | 1296 | Otherwise, if the value of the @code{delete-window} window parameter is |
| 1293 | @code{delete-window} window parameter is a function, that function is | 1297 | a function, that function is called with the argument @var{window}, in |
| 1294 | called with the argument @var{window}, in lieu of the usual action of | 1298 | lieu of the usual action of @code{delete-window}. @xref{Window |
| 1295 | @code{delete-window}. Otherwise, this function obeys the | 1299 | Parameters}. |
| 1296 | @code{window-atom} or @code{window-side} window parameter, if any. | ||
| 1297 | @xref{Window Parameters}. | ||
| 1298 | @end deffn | 1300 | @end deffn |
| 1299 | 1301 | ||
| 1300 | @deffn Command delete-other-windows &optional window | 1302 | @deffn Command delete-other-windows &optional window |
| 1301 | This function makes @var{window} fill its frame, by deleting other | 1303 | This function makes @var{window} fill its frame, deleting other windows |
| 1302 | windows as necessary. If @var{window} is omitted or @code{nil}, it | 1304 | as necessary. If @var{window} is omitted or @code{nil}, it defaults to |
| 1303 | defaults to the selected window. The return value is @code{nil}. | 1305 | the selected window. An error is signaled if @var{window} is a side |
| 1304 | 1306 | window (@pxref{Side Windows}). The return value is @code{nil}. | |
| 1305 | The behavior of this function may be altered by the window parameters | 1307 | |
| 1306 | of @var{window}, so long as the variable | 1308 | The behavior of this function may be altered by the window parameters of |
| 1307 | @code{ignore-window-parameters} is @code{nil}. If the value of | 1309 | @var{window}, so long as the variable @code{ignore-window-parameters} is |
| 1308 | the @code{delete-other-windows} window parameter is @code{t}, this | 1310 | @code{nil}. If the value of the @code{delete-other-windows} window |
| 1309 | function ignores all other window parameters. Otherwise, if the value | 1311 | parameter is @code{t}, this function ignores all other window |
| 1310 | of the @code{delete-other-windows} window parameter is a function, | 1312 | parameters. Otherwise, if the value of the @code{delete-other-windows} |
| 1311 | that function is called with the argument @var{window}, in lieu of the | 1313 | window parameter is a function, that function is called with the |
| 1312 | usual action of @code{delete-other-windows}. Otherwise, this function | 1314 | argument @var{window}, in lieu of the usual action of |
| 1313 | obeys the @code{window-atom} or @code{window-side} window parameter, | 1315 | @code{delete-other-windows}. @xref{Window Parameters}. |
| 1314 | if any. @xref{Window Parameters}. | 1316 | |
| 1317 | Also, if @code{ignore-window-parameters} is @code{nil}, this function | ||
| 1318 | does not delete any window whose @code{no-delete-other-window} parameter | ||
| 1319 | is non-@code{nil}. | ||
| 1315 | @end deffn | 1320 | @end deffn |
| 1316 | 1321 | ||
| 1317 | @deffn Command delete-windows-on &optional buffer-or-name frame | 1322 | @deffn Command delete-windows-on &optional buffer-or-name frame |
| @@ -2574,7 +2579,12 @@ assumed that when the caller specifies a non-@code{nil} | |||
| 2574 | from @code{display-buffer} in this case. | 2579 | from @code{display-buffer} in this case. |
| 2575 | @end defun | 2580 | @end defun |
| 2576 | 2581 | ||
| 2577 | To illustrate the use of action functions, consider the following | 2582 | If the @var{alist} argument of any of these functions contains a |
| 2583 | @code{window-parameters} entry, @code{display-buffer} assigns the | ||
| 2584 | elements of the associated value as window parameters of the chosen | ||
| 2585 | window. | ||
| 2586 | |||
| 2587 | To illustrate the use of action functions, consider the following | ||
| 2578 | example. | 2588 | example. |
| 2579 | 2589 | ||
| 2580 | @example | 2590 | @example |
| @@ -3068,6 +3078,295 @@ other frame on the same terminal. | |||
| 3068 | @end defopt | 3078 | @end defopt |
| 3069 | 3079 | ||
| 3070 | 3080 | ||
| 3081 | @node Side Windows | ||
| 3082 | @section Side Windows | ||
| 3083 | @cindex side windows | ||
| 3084 | @cindex main window | ||
| 3085 | @cindex main window of a frame | ||
| 3086 | |||
| 3087 | Side windows are special windows positioned at any of the four sides of | ||
| 3088 | a frame's root window (@pxref{Windows and Frames}). In practice, this | ||
| 3089 | means that the area of the frame's root window is subdivided into a main | ||
| 3090 | window and a number of side windows surrounding that main window. The | ||
| 3091 | main window is either a ``normal'' live window or specifies the area | ||
| 3092 | containing all the normal windows. | ||
| 3093 | |||
| 3094 | In their most simple form of use, side windows allow to display | ||
| 3095 | specific buffers always in the same area of a frame. Hence they can be | ||
| 3096 | regarded as a generalization of the concept provided by | ||
| 3097 | @code{display-buffer-at-bottom} (@pxref{Display Action Functions}) to | ||
| 3098 | the remaining sides of a frame. With suitable customizations, however, | ||
| 3099 | side windows can be also used to provide frame layouts similar to those | ||
| 3100 | found in so-called integrated development environments (IDEs). | ||
| 3101 | |||
| 3102 | @menu | ||
| 3103 | * Displaying Buffers in Side Windows:: An action function for displaying | ||
| 3104 | buffers in side windows. | ||
| 3105 | * Side Window Options and Functions:: Further tuning of side windows. | ||
| 3106 | * Frame Layouts with Side Windows:: Setting up frame layouts with side | ||
| 3107 | windows. | ||
| 3108 | @end menu | ||
| 3109 | |||
| 3110 | |||
| 3111 | @node Displaying Buffers in Side Windows | ||
| 3112 | @subsection Displaying Buffers in Side Windows | ||
| 3113 | |||
| 3114 | The following action function for @code{display-buffer} (@pxref{Display | ||
| 3115 | Action Functions}) creates or reuses a side window for displaying the | ||
| 3116 | specified buffer. | ||
| 3117 | |||
| 3118 | @defun display-buffer-in-side-window buffer alist | ||
| 3119 | This function displays @var{buffer} in a side window of the selected | ||
| 3120 | frame. @var{alist} is an association list of symbols and values as for | ||
| 3121 | @code{display-buffer}. The following symbols in @var{alist} are special | ||
| 3122 | for this function: | ||
| 3123 | |||
| 3124 | @table @code | ||
| 3125 | @item side | ||
| 3126 | Denotes the side of the frame where the window shall be located. Valid | ||
| 3127 | values are @code{left}, @code{top}, @code{right} and @code{bottom}. If | ||
| 3128 | unspecified, the window is located at the bottom of the frame. | ||
| 3129 | |||
| 3130 | @item slot | ||
| 3131 | Denotes a slot at the specified side where to locate the window. A | ||
| 3132 | value of zero means to preferably position the window in the middle of | ||
| 3133 | the specified side. A negative value means to use a slot preceding | ||
| 3134 | (that is, above or on the left of) the middle slot. A positive value | ||
| 3135 | means to use a slot following (that is, below or on the right of) the | ||
| 3136 | middle slot. Hence, all windows on a specific side are ordered by their | ||
| 3137 | @code{slot} value. If unspecified, the window is located in the middle | ||
| 3138 | of the specified side. | ||
| 3139 | @end table | ||
| 3140 | |||
| 3141 | If you specify the same slot on the same side for two or more different | ||
| 3142 | buffers, the buffer displayed last is shown in the corresponding window. | ||
| 3143 | Hence, slots can be used for sharing the same side window between | ||
| 3144 | buffers. | ||
| 3145 | |||
| 3146 | This function installs the @code{window-side} and @code{window-slot} | ||
| 3147 | parameters (@pxref{Window Parameters}) and makes them persistent. It | ||
| 3148 | does not install any other window parameters unless they have been | ||
| 3149 | explicitly provided via a @code{window-parameters} entry in @var{alist}. | ||
| 3150 | @end defun | ||
| 3151 | |||
| 3152 | By default, side windows cannot be split via @code{split-window} | ||
| 3153 | (@pxref{Splitting Windows}). Also, a side window is not reused or split | ||
| 3154 | by any buffer display action (@pxref{Display Action Functions}) unless | ||
| 3155 | it is explicitly specified as target of that action. Note also that | ||
| 3156 | @code{delete-other-windows} cannot make a side window the only window on | ||
| 3157 | its frame (@pxref{Deleting Windows}). | ||
| 3158 | |||
| 3159 | Once set up, side windows also change the behavior of the commands | ||
| 3160 | @code{switch-to-prev-buffer} and @code{switch-to-next-buffer} | ||
| 3161 | (@pxref{Window History}). In particular, these commands will refrain | ||
| 3162 | from showing, in a side window, buffers that have not been displayed in | ||
| 3163 | that window before. And, they will refrain from having a normal, | ||
| 3164 | non-side window show a buffer that has been already displayed in a side | ||
| 3165 | window. A notable exception to the latter rule occurs when an | ||
| 3166 | application, after displaying a buffer, resets that buffer's local | ||
| 3167 | variables. | ||
| 3168 | |||
| 3169 | |||
| 3170 | @node Side Window Options and Functions | ||
| 3171 | @subsection Side Window Options and Functions | ||
| 3172 | |||
| 3173 | The following options provide additional control over the placement of | ||
| 3174 | side windows. | ||
| 3175 | |||
| 3176 | @defopt window-sides-vertical | ||
| 3177 | If non-@code{nil}, this means that the side windows on the left and | ||
| 3178 | right of a frame occupy the frame's full height. Otherwise, the side | ||
| 3179 | windows on the top and bottom of the frame occupy the frame's full | ||
| 3180 | width. | ||
| 3181 | @end defopt | ||
| 3182 | |||
| 3183 | @defopt window-sides-slots | ||
| 3184 | This option specifies the maximum number of side windows on each side of | ||
| 3185 | a frame. The value is a list of four elements specifying the number of | ||
| 3186 | side window slots on (in this order) the left, top, right and bottom of | ||
| 3187 | each frame. If an element is a number, this means to display at most | ||
| 3188 | that many windows on the corresponding side. If an element is | ||
| 3189 | @code{nil}, this means there's no bound on the number of slots on that | ||
| 3190 | side. | ||
| 3191 | |||
| 3192 | If any of the specified values is zero, no window can be created on the | ||
| 3193 | corresponding side. @code{display-buffer-in-side-window} will not | ||
| 3194 | signal an error in that case but return @code{nil}. If a specified | ||
| 3195 | value just forbids the creation of an additional side window, the most | ||
| 3196 | suitable window on that side is reused and may have its | ||
| 3197 | @code{window-slot} parameter changed accordingly. | ||
| 3198 | @end defopt | ||
| 3199 | |||
| 3200 | @defopt window-sides-reversed | ||
| 3201 | This option specifies whether top/bottom side windows should appear in | ||
| 3202 | reverse order. When this is @code{nil}, side windows on the top and | ||
| 3203 | bottom of a frame are always drawn from left to right with increasing | ||
| 3204 | slot values. When this is @code{t}, the drawing order is reversed and | ||
| 3205 | side windows on the top and bottom of a frame are drawn from right to | ||
| 3206 | left with increasing slot values. | ||
| 3207 | |||
| 3208 | When this is @code{bidi}, the drawing order is reversed if and only if | ||
| 3209 | the value of @code{bidi-paragraph-direction} is @code{right-to-left} in | ||
| 3210 | the buffer displayed in the window most recently selected within the | ||
| 3211 | main window area of this frame. Sometimes that window may be hard to | ||
| 3212 | find, so heuristics are used to avoid that the drawing order changes | ||
| 3213 | inadvertently when another window gets selected. | ||
| 3214 | |||
| 3215 | The layout of side windows on the left or right of a frame is not | ||
| 3216 | affected by the value of this variable. | ||
| 3217 | @end defopt | ||
| 3218 | |||
| 3219 | When a frame has side windows, the following function returns the main | ||
| 3220 | window of that frame. | ||
| 3221 | |||
| 3222 | @defun window-main-window &optional frame | ||
| 3223 | This function returns the main window of the specified @var{frame}. The | ||
| 3224 | optional argument @var{frame} must be a live frame and defaults to the | ||
| 3225 | selected one. | ||
| 3226 | |||
| 3227 | If @var{frame} has no side windows, it returns @var{frame}'s root | ||
| 3228 | window. Otherwise, it returns either an internal non-side window such | ||
| 3229 | that all other non-side windows on @var{frame} descend from it, or the | ||
| 3230 | single live non-side window of @var{frame}. Note that the main window | ||
| 3231 | of a frame cannot be deleted via @code{delete-window}. | ||
| 3232 | @end defun | ||
| 3233 | |||
| 3234 | The following command is handy to toggle the appearance of all side | ||
| 3235 | windows on a specified frame. | ||
| 3236 | |||
| 3237 | @deffn Command window-toggle-side-windows &optional frame | ||
| 3238 | This command toggles side windows on the specified @var{frame}. The | ||
| 3239 | optional argument @var{frame} must be a live frame and defaults to the | ||
| 3240 | selected one. | ||
| 3241 | |||
| 3242 | If @var{frame} has at least one side window, this command saves the | ||
| 3243 | state of @var{frame}'s root window in the @var{frame}'s | ||
| 3244 | @code{window-state} frame parameter and deletes all side windows on | ||
| 3245 | @var{frame} afterwards. | ||
| 3246 | |||
| 3247 | If @var{frame} has no side window but a @code{window-state} parameter, | ||
| 3248 | it uses that parameter's value to restore the side windows on | ||
| 3249 | @var{frame} leaving @var{frame}'s main window alone. | ||
| 3250 | |||
| 3251 | An error is signaled if @var{frame} has no side window and no saved | ||
| 3252 | state is found. | ||
| 3253 | @end deffn | ||
| 3254 | |||
| 3255 | |||
| 3256 | @node Frame Layouts with Side Windows | ||
| 3257 | @subsection Frame Layouts with Side Windows | ||
| 3258 | |||
| 3259 | Side windows can be used to create more complex frame layouts like those | ||
| 3260 | provided by integrated development environments (IDEs). In such | ||
| 3261 | layouts, the area of the main window is where the normal editing | ||
| 3262 | activities take place. Side windows are not conceived for editing in | ||
| 3263 | the usual sense. Rather, they are supposed to display information | ||
| 3264 | complementary to the current editing activity, like lists of files, tags | ||
| 3265 | or buffers, help information, search or grep results or shell output. | ||
| 3266 | |||
| 3267 | The layout of such a frame might appear as follows: | ||
| 3268 | |||
| 3269 | @smallexample | ||
| 3270 | @group | ||
| 3271 | ___________________________________ | ||
| 3272 | | *Buffer List* | | ||
| 3273 | |___________________________________| | ||
| 3274 | | | | | | ||
| 3275 | | * | | * | | ||
| 3276 | | d | | T | | ||
| 3277 | | i | | a | | ||
| 3278 | | r | Main Window Area | g | | ||
| 3279 | | e | | s | | ||
| 3280 | | d | | * | | ||
| 3281 | | * | | | | ||
| 3282 | |_____|_______________________|_____| | ||
| 3283 | | *help*/*grep*/ | *shell*/ | | ||
| 3284 | | *Completions* | *compilation* | | ||
| 3285 | |_________________|_________________| | ||
| 3286 | | Echo Area | | ||
| 3287 | |___________________________________| | ||
| 3288 | |||
| 3289 | |||
| 3290 | @end group | ||
| 3291 | @end smallexample | ||
| 3292 | |||
| 3293 | The following example illustrates how window parameters (@pxref{Window | ||
| 3294 | Parameters}) can be used with @code{display-buffer-in-side-window} | ||
| 3295 | (@pxref{Displaying Buffers in Side Windows}) to set up code for | ||
| 3296 | producing the frame sketched above. | ||
| 3297 | |||
| 3298 | @example | ||
| 3299 | @group | ||
| 3300 | (defvar parameters | ||
| 3301 | '(window-parameters . ((no-other-window . t) (no-delete-other-window . t)))) | ||
| 3302 | |||
| 3303 | (setq fit-window-to-buffer-horizontally t) | ||
| 3304 | (setq window-resize-pixelwise t) | ||
| 3305 | |||
| 3306 | (setq | ||
| 3307 | display-buffer-alist | ||
| 3308 | `(("\\*Buffer List\\*" display-buffer-in-side-window | ||
| 3309 | (side . top) (slot . 0) (window-height . fit-window-to-buffer) | ||
| 3310 | (preserve-size . (nil . t)) ,parameters) | ||
| 3311 | ("\\*Tags List\\*" display-buffer-in-side-window | ||
| 3312 | (side . right) (slot . 0) (window-width . fit-window-to-buffer) | ||
| 3313 | (preserve-size . (t . nil)) ,parameters) | ||
| 3314 | ("\\*\\(?:help\\|grep\\|Completions\\)\\*" display-buffer-in-side-window | ||
| 3315 | (side . bottom) (slot . -1) (preserve-size . (nil . t)) ,parameters) | ||
| 3316 | ("\\*\\(?:shell\\|compilation\\)\\*" display-buffer-in-side-window | ||
| 3317 | (side . bottom) (slot . 1) (preserve-size . (nil . t)) ,parameters))) | ||
| 3318 | @end group | ||
| 3319 | @end example | ||
| 3320 | |||
| 3321 | This specifies @code{display-buffer-alist} entries (@pxref{Choosing | ||
| 3322 | Window}) for buffers with fixed names. In particular, it asks for | ||
| 3323 | showing @file{*Buffer List*} with adjustable height at the top of the | ||
| 3324 | frame and @file{*Tags List*} with adjustable width on the frame's right. | ||
| 3325 | It also asks for having the @file{*help*}, @file{*grep*} and | ||
| 3326 | @file{*Completions*} buffers share a window on the bottom left side of | ||
| 3327 | the frame and the @file{*shell*} and @file{*compilation*} buffers appear | ||
| 3328 | in a window on the bottom right side of the frame. | ||
| 3329 | |||
| 3330 | Note that the option @code{fit-window-to-buffer-horizontally} must | ||
| 3331 | have a non-@code{nil} value in order to allow horizontal adjustment of | ||
| 3332 | windows. We also added entries that ask for preserving the height of | ||
| 3333 | side windows at the top and bottom of the frame and the width of side | ||
| 3334 | windows at the left or right of the frame. To assure that side windows | ||
| 3335 | retain their respective sizes when maximizing the associated frame, we | ||
| 3336 | have also set the variable @code{window-resize-pixelwise}. | ||
| 3337 | @xref{Resizing Windows}. | ||
| 3338 | |||
| 3339 | The last form also makes sure that none of the side windows it | ||
| 3340 | creates are accessible via @kbd{C-x o} by installing a | ||
| 3341 | @code{no-other-window} parameter for each of these windows. In addition | ||
| 3342 | it also makes sure that side windows are not deleted via @kbd{C-x 1} by | ||
| 3343 | installing a @code{no-delete-other-window} parameter on each of these | ||
| 3344 | windows. | ||
| 3345 | |||
| 3346 | Since @code{dired} buffers have no fixed names, we use a special | ||
| 3347 | function @code{dired-default-directory-on-left} in order to display a | ||
| 3348 | lean directory buffer on the left side of the frame. | ||
| 3349 | |||
| 3350 | @example | ||
| 3351 | @group | ||
| 3352 | (defun dired-default-directory-on-left () | ||
| 3353 | "Display `default-directory' in side window on left, hiding details." | ||
| 3354 | (interactive) | ||
| 3355 | (let ((buffer (dired-noselect default-directory))) | ||
| 3356 | (with-current-buffer buffer (dired-hide-details-mode t)) | ||
| 3357 | (display-buffer-in-side-window | ||
| 3358 | buffer `((side . left) (slot . 0) | ||
| 3359 | (window-width . fit-window-to-buffer) | ||
| 3360 | (preserve-size . (t . nil)) ,parameters)))) | ||
| 3361 | @end group | ||
| 3362 | @end example | ||
| 3363 | |||
| 3364 | Evaluating the preceding forms and typing, in any order, @kbd{M-x | ||
| 3365 | list-buffers}, @kbd{C-h f}, @kbd{M-x shell}, @kbd{M-x list-tags} and | ||
| 3366 | @kbd{M-x dired-default-directory-on-left} should now reproduce the frame | ||
| 3367 | layout sketched above. | ||
| 3368 | |||
| 3369 | |||
| 3071 | @node Window Point | 3370 | @node Window Point |
| 3072 | @section Windows and Point | 3371 | @section Windows and Point |
| 3073 | @cindex window position | 3372 | @cindex window position |
| @@ -4242,6 +4541,25 @@ is @code{safe}, this means windows can get as small as one line | |||
| 4242 | and/or two columns. | 4541 | and/or two columns. |
| 4243 | @end defun | 4542 | @end defun |
| 4244 | 4543 | ||
| 4544 | The functions @code{window-state-get} and @code{window-state-put} also | ||
| 4545 | allow to exchange the contents of two live windows. The following | ||
| 4546 | function does precisely that: | ||
| 4547 | |||
| 4548 | @deffn Command window-swap-states &optional window-1 window-2 size | ||
| 4549 | This command swaps the states of the two live windows @var{window-1} and | ||
| 4550 | @var{window-2}. @var{window-1} must specify a live window and defaults | ||
| 4551 | to the selected one. @var{window-2} must specify a live window and | ||
| 4552 | defaults to the window following @var{window-1} in the cyclic ordering | ||
| 4553 | of windows, excluding minibuffer windows and including live windows on | ||
| 4554 | all visible frames. | ||
| 4555 | |||
| 4556 | Optional argument @var{size} non-@code{nil} means to try swapping the | ||
| 4557 | sizes of @var{window-1} and @var{window-2} as well. A value of | ||
| 4558 | @code{height} means to swap heights only, a value of @code{width} | ||
| 4559 | means to swap widths only, while @code{t} means to swap both widths | ||
| 4560 | and heights, if possible. Frames are not resized by this function. | ||
| 4561 | @end deffn | ||
| 4562 | |||
| 4245 | 4563 | ||
| 4246 | @node Window Parameters | 4564 | @node Window Parameters |
| 4247 | @section Window Parameters | 4565 | @section Window Parameters |
| @@ -4279,6 +4597,7 @@ earlier by @code{window-state-get}, all cloned windows have their | |||
| 4279 | parameters reset to @code{nil}. The following variable allows you to | 4597 | parameters reset to @code{nil}. The following variable allows you to |
| 4280 | override the standard behavior: | 4598 | override the standard behavior: |
| 4281 | 4599 | ||
| 4600 | @cindex persistent window parameters | ||
| 4282 | @defvar window-persistent-parameters | 4601 | @defvar window-persistent-parameters |
| 4283 | This variable is an alist specifying which parameters get saved by | 4602 | This variable is an alist specifying which parameters get saved by |
| 4284 | @code{current-window-configuration} and @code{window-state-get}, and | 4603 | @code{current-window-configuration} and @code{window-state-get}, and |
| @@ -4308,10 +4627,10 @@ may fail with an @code{invalid-read-syntax} error. | |||
| 4308 | @end defvar | 4627 | @end defvar |
| 4309 | 4628 | ||
| 4310 | Some functions (notably @code{delete-window}, | 4629 | Some functions (notably @code{delete-window}, |
| 4311 | @code{delete-other-windows} and @code{split-window}), may behave specially | 4630 | @code{delete-other-windows} and @code{split-window}), may behave |
| 4312 | when their @var{window} argument has a parameter set. You can override | 4631 | specially when the window specified by their @var{window} argument has |
| 4313 | such special behavior by binding the following variable to a | 4632 | the homonymous parameter set. You can override such special behavior by |
| 4314 | non-@code{nil} value: | 4633 | binding the following variable to a non-@code{nil} value: |
| 4315 | 4634 | ||
| 4316 | @defvar ignore-window-parameters | 4635 | @defvar ignore-window-parameters |
| 4317 | If this variable is non-@code{nil}, some standard functions do not | 4636 | If this variable is non-@code{nil}, some standard functions do not |
| @@ -4337,6 +4656,10 @@ This parameter affects the execution of @code{delete-window} | |||
| 4337 | This parameter affects the execution of @code{delete-other-windows} | 4656 | This parameter affects the execution of @code{delete-other-windows} |
| 4338 | (@pxref{Deleting Windows}). | 4657 | (@pxref{Deleting Windows}). |
| 4339 | 4658 | ||
| 4659 | @item @code{no-delete-other-window} | ||
| 4660 | This parameter marks the window as not deletable by | ||
| 4661 | @code{delete-other-windows} (@pxref{Deleting Windows}). | ||
| 4662 | |||
| 4340 | @item @code{split-window} | 4663 | @item @code{split-window} |
| 4341 | This parameter affects the execution of @code{split-window} | 4664 | This parameter affects the execution of @code{split-window} |
| 4342 | (@pxref{Splitting Windows}). | 4665 | (@pxref{Splitting Windows}). |
| @@ -4387,6 +4710,10 @@ The fourth element is the buffer whose display caused the creation of | |||
| 4387 | this parameter. @code{quit-restore-window} deletes the specified window | 4710 | this parameter. @code{quit-restore-window} deletes the specified window |
| 4388 | only if it still shows that buffer. | 4711 | only if it still shows that buffer. |
| 4389 | 4712 | ||
| 4713 | @item @code{window-side} @code{window-slot} | ||
| 4714 | These parameters are used for implementing side windows (@pxref{Side | ||
| 4715 | Windows}). | ||
| 4716 | |||
| 4390 | @item @code{min-margins} | 4717 | @item @code{min-margins} |
| 4391 | The value of this parameter is a cons cell whose @sc{car} and @sc{cdr}, | 4718 | The value of this parameter is a cons cell whose @sc{car} and @sc{cdr}, |
| 4392 | if non-@code{nil}, specify the minimum values (in columns) for the left | 4719 | if non-@code{nil}, specify the minimum values (in columns) for the left |
| @@ -4409,8 +4736,7 @@ applications. It might be replaced by an improved solution in future | |||
| 4409 | versions of Emacs. | 4736 | versions of Emacs. |
| 4410 | @end table | 4737 | @end table |
| 4411 | 4738 | ||
| 4412 | There are additional parameters @code{window-atom} and @code{window-side}; | 4739 | The @code{window-atom} parameter is used for implemeting atomic windows. |
| 4413 | these are reserved and should not be used by applications. | ||
| 4414 | 4740 | ||
| 4415 | 4741 | ||
| 4416 | @node Window Hooks | 4742 | @node Window Hooks |
| @@ -611,6 +611,27 @@ collection). | |||
| 611 | ** The new functions 'make-nearby-temp-file' and 'temporary-file-directory' | 611 | ** The new functions 'make-nearby-temp-file' and 'temporary-file-directory' |
| 612 | can be used for creation of temporary files of remote or mounted directories. | 612 | can be used for creation of temporary files of remote or mounted directories. |
| 613 | 613 | ||
| 614 | ** Changes in Frame- and Window- Handling | ||
| 615 | |||
| 616 | +++ | ||
| 617 | *** Support for side windows is now official. The display action | ||
| 618 | function `display-buffer-in-side-window' will display its buffer in a | ||
| 619 | side window. Functions for toggling all side windows on a frame, | ||
| 620 | changing and reversing the layout of side windows and returning the main | ||
| 621 | (major non-side) window of a frame are provided. For details consult | ||
| 622 | the section "Side Windows" in the Elisp manual. | ||
| 623 | |||
| 624 | +++ | ||
| 625 | *** New `display-buffer' alist entry `window-parameters' allows to | ||
| 626 | assign window parameters to the window used for displaying the buffer. | ||
| 627 | |||
| 628 | +++ | ||
| 629 | *** New window parameter `no-delete-other-window' prevents that | ||
| 630 | its window gets deleted by `delete-other-windows'. | ||
| 631 | |||
| 632 | +++ | ||
| 633 | *** New command `window-swap-states' swaps the states of two live | ||
| 634 | windows. | ||
| 614 | 635 | ||
| 615 | * Changes in Emacs 26.1 on Non-Free Operating Systems | 636 | * Changes in Emacs 26.1 on Non-Free Operating Systems |
| 616 | 637 | ||
diff --git a/lisp/window.el b/lisp/window.el index 6728ea34a83..4511267149c 100644 --- a/lisp/window.el +++ b/lisp/window.el | |||
| @@ -657,7 +657,7 @@ failed." | |||
| 657 | (setq window (window-normalize-window window)) | 657 | (setq window (window-normalize-window window)) |
| 658 | (setq root (window-atom-root window)) | 658 | (setq root (window-atom-root window)) |
| 659 | ;; Split off new window. | 659 | ;; Split off new window. |
| 660 | (when (setq new (split-window window nil side)) | 660 | (when (setq new (split-window-no-error window nil side)) |
| 661 | (window-make-atom | 661 | (window-make-atom |
| 662 | (if (and root (not (eq root window))) | 662 | (if (and root (not (eq root window))) |
| 663 | ;; When WINDOW was part of an atomic window and we did not | 663 | ;; When WINDOW was part of an atomic window and we did not |
| @@ -709,24 +709,50 @@ no child windows or one of its child windows is not atomic." | |||
| 709 | (window--atom-check-1 (frame-root-window frame))) | 709 | (window--atom-check-1 (frame-root-window frame))) |
| 710 | 710 | ||
| 711 | ;; Side windows. | 711 | ;; Side windows. |
| 712 | (defvar window-sides '(left top right bottom) | ||
| 713 | "Window sides.") | ||
| 714 | |||
| 715 | (defcustom window-sides-vertical nil | 712 | (defcustom window-sides-vertical nil |
| 716 | "If non-nil, left and right side windows are full height. | 713 | "If non-nil, left and right side windows occupy full frame height. |
| 717 | Otherwise, top and bottom side windows are full width." | 714 | If nil, top and bottom side windows occupy full frame width." |
| 718 | :type 'boolean | 715 | :type 'boolean |
| 716 | :initialize 'custom-initialize-default | ||
| 717 | :set 'window--sides-verticalize | ||
| 719 | :group 'windows | 718 | :group 'windows |
| 720 | :version "24.1") | 719 | :version "26.1") |
| 720 | |||
| 721 | (defcustom window-sides-reversed nil | ||
| 722 | "Whether top/bottom side windows appear in reverse order. | ||
| 723 | When this is nil, side windows on the top and bottom of a frame | ||
| 724 | are always drawn from left to right with increasing slot values. | ||
| 725 | When this is t, side windows on the top and bottom of a frame are | ||
| 726 | always drawn from right to left with increasing slot values. | ||
| 727 | |||
| 728 | When this is `bidi', the drawing order is like that for the value | ||
| 729 | t if the value of `bidi-paragraph-direction' is `right-to-left' | ||
| 730 | in the buffer most recently shown in the window selected within | ||
| 731 | the main window area of this frame. | ||
| 732 | |||
| 733 | The layout of side windows on the left or right of a frame is not | ||
| 734 | affected by the value of this variable." | ||
| 735 | :type | ||
| 736 | '(choice (const :tag "Never" nil) | ||
| 737 | (const :tag "Bidi" bidi) | ||
| 738 | (const :tag "Always" t)) | ||
| 739 | :initialize 'custom-initialize-default | ||
| 740 | :set 'window--sides-reverse | ||
| 741 | :group 'windows | ||
| 742 | :version "26.1") | ||
| 721 | 743 | ||
| 722 | (defcustom window-sides-slots '(nil nil nil nil) | 744 | (defcustom window-sides-slots '(nil nil nil nil) |
| 723 | "Maximum number of side window slots. | 745 | "Number of available side window slots on each side of a frame. |
| 724 | The value is a list of four elements specifying the number of | 746 | The value is a list of four elements specifying the maximum |
| 725 | side window slots on (in this order) the left, top, right and | 747 | number of side windows that may be created on the left, top, |
| 726 | bottom side of each frame. If an element is a number, this means | 748 | right and bottom side of any frame. |
| 727 | to display at most that many side windows on the corresponding | 749 | |
| 728 | side. If an element is nil, this means there's no bound on the | 750 | If an element is a number, `display-buffer-in-side-window' will |
| 729 | number of slots on that side." | 751 | refrain from making a new side window if the number of windows on |
| 752 | that side is equal to or exceeds that number. Rather, it will | ||
| 753 | reuse the window whose `window-slot' value is nearest to the slot | ||
| 754 | specified via its ALIST argument. If an element is nil, this | ||
| 755 | means there's no bound on the number of windows on that side." | ||
| 730 | :version "24.1" | 756 | :version "24.1" |
| 731 | :risky t | 757 | :risky t |
| 732 | :type | 758 | :type |
| @@ -734,56 +760,94 @@ number of slots on that side." | |||
| 734 | :value (nil nil nil nil) | 760 | :value (nil nil nil nil) |
| 735 | (choice | 761 | (choice |
| 736 | :tag "Left" | 762 | :tag "Left" |
| 737 | :help-echo "Maximum slots of left side window." | 763 | :help-echo "Maximum number of left side windows." |
| 738 | :value nil | 764 | :value nil |
| 739 | :format "%[Left%] %v\n" | 765 | :format "%[Left%] %v\n" |
| 740 | (const :tag "Unlimited" :format "%t" nil) | 766 | (const :tag "Unlimited" :format "%t" nil) |
| 741 | (integer :tag "Number" :value 2 :size 5)) | 767 | (integer :tag "Number" :value 2 :size 5)) |
| 742 | (choice | 768 | (choice |
| 743 | :tag "Top" | 769 | :tag "Top" |
| 744 | :help-echo "Maximum slots of top side window." | 770 | :help-echo "Maximum number of top side windows." |
| 745 | :value nil | 771 | :value nil |
| 746 | :format "%[Top%] %v\n" | 772 | :format "%[Top%] %v\n" |
| 747 | (const :tag "Unlimited" :format "%t" nil) | 773 | (const :tag "Unlimited" :format "%t" nil) |
| 748 | (integer :tag "Number" :value 3 :size 5)) | 774 | (integer :tag "Number" :value 3 :size 5)) |
| 749 | (choice | 775 | (choice |
| 750 | :tag "Right" | 776 | :tag "Right" |
| 751 | :help-echo "Maximum slots of right side window." | 777 | :help-echo "Maximum number of right side windows." |
| 752 | :value nil | 778 | :value nil |
| 753 | :format "%[Right%] %v\n" | 779 | :format "%[Right%] %v\n" |
| 754 | (const :tag "Unlimited" :format "%t" nil) | 780 | (const :tag "Unlimited" :format "%t" nil) |
| 755 | (integer :tag "Number" :value 2 :size 5)) | 781 | (integer :tag "Number" :value 2 :size 5)) |
| 756 | (choice | 782 | (choice |
| 757 | :tag "Bottom" | 783 | :tag "Bottom" |
| 758 | :help-echo "Maximum slots of bottom side window." | 784 | :help-echo "Maximum number of bottom side windows." |
| 759 | :value nil | 785 | :value nil |
| 760 | :format "%[Bottom%] %v\n" | 786 | :format "%[Bottom%] %v\n" |
| 761 | (const :tag "Unlimited" :format "%t" nil) | 787 | (const :tag "Unlimited" :format "%t" nil) |
| 762 | (integer :tag "Number" :value 3 :size 5))) | 788 | (integer :tag "Number" :value 3 :size 5))) |
| 763 | :group 'windows) | 789 | :group 'windows) |
| 764 | 790 | ||
| 765 | (defun window--side-window-p (window) | 791 | (defvar-local window--sides-shown nil |
| 766 | "Return non-nil if WINDOW is a side window or the parent of one." | 792 | "Non-nil if this buffer was shown in a side window once. |
| 767 | (or (window-parameter window 'window-side) | 793 | If this variable is non-nil in a buffer, `switch-to-prev-buffer' |
| 768 | (and (window-child window) | 794 | and `switch-to-next-buffer' will refrain from showing this buffer |
| 769 | (or (window-parameter | 795 | within the main window area. `display-buffer-in-side-window' |
| 770 | (window-child window) 'window-side) | 796 | sets this variable automatically. |
| 771 | (window-parameter | 797 | |
| 772 | (window-last-child window) 'window-side))))) | 798 | Killing buffer local variables after showing the buffer in a side |
| 773 | 799 | window annihilates any effect provided by this variable.") | |
| 774 | (defun window--major-non-side-window (&optional frame) | 800 | |
| 775 | "Return the major non-side window of frame FRAME. | 801 | (defvar window--sides-inhibit-check nil |
| 802 | "Non-nil means inhibit any checks on side windows.") | ||
| 803 | |||
| 804 | (defun window--sides-reverse-on-frame-p (frame) | ||
| 805 | "Return non-nil when side windows should appear reversed on FRAME. | ||
| 806 | This uses some heuristics to guess the user's intentions when the | ||
| 807 | selected window of FRAME is a side window ." | ||
| 808 | (cond | ||
| 809 | ;; Reverse when `window-sides-reversed' is t. Do not reverse when | ||
| 810 | ;; `window-sides-reversed' is nil. | ||
| 811 | ((memq window-sides-reversed '(nil t)) | ||
| 812 | window-sides-reversed) | ||
| 813 | ;; Reverse when FRAME's selected window shows a right-to-left buffer. | ||
| 814 | ((let ((window (frame-selected-window frame))) | ||
| 815 | (when (and (not (window-parameter window 'window-side)) | ||
| 816 | (or (not (window-minibuffer-p window)) | ||
| 817 | (setq window (minibuffer-selected-window)))) | ||
| 818 | (with-current-buffer (window-buffer window) | ||
| 819 | (eq bidi-paragraph-direction 'right-to-left))))) | ||
| 820 | ;; Reverse when FRAME's `window-sides-main-selected-window' parameter | ||
| 821 | ;; specifies a live window showing a right-to-left buffer. | ||
| 822 | ((let ((window (frame-parameter | ||
| 823 | frame 'window-sides-main-selected-window))) | ||
| 824 | (when (window-live-p window) | ||
| 825 | (with-current-buffer (window-buffer window) | ||
| 826 | (eq bidi-paragraph-direction 'right-to-left))))) | ||
| 827 | ;; Reverse when all windows in FRAME's main window show right-to-left | ||
| 828 | ;; buffers. | ||
| 829 | (t | ||
| 830 | (catch 'found | ||
| 831 | (walk-window-subtree | ||
| 832 | (lambda (window) | ||
| 833 | (with-current-buffer (window-buffer window) | ||
| 834 | (when (eq bidi-paragraph-direction 'left-to-right) | ||
| 835 | (throw 'found nil)))) | ||
| 836 | (window-main-window frame)) | ||
| 837 | t)))) | ||
| 838 | |||
| 839 | (defun window-main-window (&optional frame) | ||
| 840 | "Return the main window of specified FRAME. | ||
| 776 | The optional argument FRAME must be a live frame and defaults to | 841 | The optional argument FRAME must be a live frame and defaults to |
| 777 | the selected one. | 842 | the selected one. |
| 778 | 843 | ||
| 779 | If FRAME has at least one side window, the major non-side window | 844 | If FRAME has no side windows, return FRAME's root window. |
| 780 | is either an internal non-side window such that all other | 845 | Otherwise, return either an internal non-side window such that |
| 781 | non-side windows on FRAME descend from it, or the single live | 846 | all other non-side windows on FRAME descend from it, or the |
| 782 | non-side window of FRAME. If FRAME has no side windows, return | 847 | single live non-side window of FRAME." |
| 783 | its root window." | ||
| 784 | (let ((frame (window-normalize-frame frame)) | 848 | (let ((frame (window-normalize-frame frame)) |
| 785 | major sibling) | 849 | main sibling) |
| 786 | ;; Set major to the _last_ window found by `walk-window-tree' that | 850 | ;; Set main to the _last_ window found by `walk-window-tree' that |
| 787 | ;; is not a side window but has a side window as its sibling. | 851 | ;; is not a side window but has a side window as its sibling. |
| 788 | (walk-window-tree | 852 | (walk-window-tree |
| 789 | (lambda (window) | 853 | (lambda (window) |
| @@ -792,16 +856,20 @@ its root window." | |||
| 792 | (window-parameter sibling 'window-side)) | 856 | (window-parameter sibling 'window-side)) |
| 793 | (and (setq sibling (window-next-sibling window)) | 857 | (and (setq sibling (window-next-sibling window)) |
| 794 | (window-parameter sibling 'window-side))) | 858 | (window-parameter sibling 'window-side))) |
| 795 | (setq major window))) | 859 | (setq main window))) |
| 796 | frame t 'nomini) | 860 | frame t 'nomini) |
| 797 | (or major (frame-root-window frame)))) | 861 | (or main (frame-root-window frame)))) |
| 798 | 862 | ||
| 799 | (defun window--major-side-window (side) | 863 | (defun window--make-major-side-window-next-to (side) |
| 800 | "Return major side window on SIDE. | 864 | "Return window to split for making a major side window. |
| 801 | SIDE must be one of the symbols `left', `top', `right' or | 865 | SIDE must be one of the symbols `left', `top', `right' or |
| 802 | `bottom'. Return nil if no such window exists." | 866 | `bottom'. |
| 867 | |||
| 868 | This is an auxiliary function of `window--make-major-side-window' | ||
| 869 | and must not be called when a window on SIDE exists already." | ||
| 803 | (let ((root (frame-root-window)) | 870 | (let ((root (frame-root-window)) |
| 804 | window) | 871 | (window--sides-inhibit-check t) |
| 872 | window) | ||
| 805 | ;; (1) If a window on the opposite side exists, return that window's | 873 | ;; (1) If a window on the opposite side exists, return that window's |
| 806 | ;; sibling. | 874 | ;; sibling. |
| 807 | ;; (2) If the new window shall span the entire side, return the | 875 | ;; (2) If the new window shall span the entire side, return the |
| @@ -839,35 +907,37 @@ SIDE must be one of the symbols `left', `top', `right' or | |||
| 839 | (window-prev-sibling window)) | 907 | (window-prev-sibling window)) |
| 840 | (t root)))))) | 908 | (t root)))))) |
| 841 | 909 | ||
| 842 | (defun display-buffer-in-major-side-window (buffer side slot &optional alist) | 910 | (defun window--make-major-side-window (buffer side slot &optional alist) |
| 843 | "Display BUFFER in a new window on SIDE of the selected frame. | 911 | "Display BUFFER in a new major side window on the selected frame. |
| 844 | SIDE must be one of `left', `top', `right' or `bottom'. SLOT | 912 | SIDE must be one of `left', `top', `right' or `bottom'. SLOT |
| 845 | specifies the slot to use. ALIST is an association list of | 913 | specifies the slot to use. ALIST is an association list of |
| 846 | symbols and values as passed to `display-buffer-in-side-window'. | 914 | symbols and values as passed to `display-buffer-in-side-window'. |
| 847 | This function may be called only if no window on SIDE exists yet. | 915 | Return the new window, nil if its creation failed. |
| 848 | The new window automatically becomes the \"major\" side window on | 916 | |
| 849 | SIDE. Return the new window, nil if its creation window failed." | 917 | This is an auxiliary function of `display-buffer-in-side-window' |
| 918 | and may be called only if no window on SIDE exists yet." | ||
| 850 | (let* ((left-or-right (memq side '(left right))) | 919 | (let* ((left-or-right (memq side '(left right))) |
| 851 | (major (window--major-side-window side)) | 920 | (next-to (window--make-major-side-window-next-to side)) |
| 852 | (on-side (cond | 921 | (on-side (cond |
| 853 | ((eq side 'top) 'above) | 922 | ((eq side 'top) 'above) |
| 854 | ((eq side 'bottom) 'below) | 923 | ((eq side 'bottom) 'below) |
| 855 | (t side))) | 924 | (t side))) |
| 925 | (window--sides-inhibit-check t) | ||
| 856 | ;; The following two bindings will tell `split-window' to take | 926 | ;; The following two bindings will tell `split-window' to take |
| 857 | ;; the space for the new window from `major' and not make a new | 927 | ;; the space for the new window from the selected frame's main |
| 858 | ;; parent window unless needed. | 928 | ;; window and not make a new parent window unless needed. |
| 859 | (window-combination-resize 'side) | 929 | (window-combination-resize 'side) |
| 860 | (window-combination-limit nil) | 930 | (window-combination-limit nil) |
| 861 | (new (split-window major nil on-side))) | 931 | (window (split-window-no-error next-to nil on-side))) |
| 862 | (when new | 932 | (when window |
| 863 | ;; Initialize `window-side' parameter of new window to SIDE. | 933 | ;; Initialize `window-side' parameter of new window to SIDE and |
| 864 | (set-window-parameter new 'window-side side) | 934 | ;; make that parameter persistent. |
| 865 | ;; Install `window-slot' parameter of new window. | 935 | (set-window-parameter window 'window-side side) |
| 866 | (set-window-parameter new 'window-slot slot) | 936 | (add-to-list 'window-persistent-parameters '(window-side . writable)) |
| 867 | ;; Install `delete-window' parameter thus making sure that when | 937 | ;; Install `window-slot' parameter of new window and make that |
| 868 | ;; the new window is deleted, a side window on the opposite side | 938 | ;; parameter persistent. |
| 869 | ;; does not get resized. | 939 | (set-window-parameter window 'window-slot slot) |
| 870 | (set-window-parameter new 'delete-window 'delete-side-window) | 940 | (add-to-list 'window-persistent-parameters '(window-slot . writable)) |
| 871 | ;; Auto-adjust height/width of new window unless a size has been | 941 | ;; Auto-adjust height/width of new window unless a size has been |
| 872 | ;; explicitly requested. | 942 | ;; explicitly requested. |
| 873 | (unless (if left-or-right | 943 | (unless (if left-or-right |
| @@ -882,15 +952,10 @@ SIDE. Return the new window, nil if its creation window failed." | |||
| 882 | ;; root window. | 952 | ;; root window. |
| 883 | 4)) | 953 | 4)) |
| 884 | alist))) | 954 | alist))) |
| 885 | ;; Install BUFFER in new window and return NEW. | 955 | (with-current-buffer buffer |
| 886 | (window--display-buffer buffer new 'window alist 'side)))) | 956 | (setq window--sides-shown t)) |
| 887 | 957 | ;; Install BUFFER in new window and return WINDOW. | |
| 888 | (defun delete-side-window (window) | 958 | (window--display-buffer buffer window 'window alist 'side)))) |
| 889 | "Delete side window WINDOW." | ||
| 890 | (let ((window-combination-resize | ||
| 891 | (window-parameter (window-parent window) 'window-side)) | ||
| 892 | (ignore-window-parameters t)) | ||
| 893 | (delete-window window))) | ||
| 894 | 959 | ||
| 895 | (defun display-buffer-in-side-window (buffer alist) | 960 | (defun display-buffer-in-side-window (buffer alist) |
| 896 | "Display BUFFER in a side window of the selected frame. | 961 | "Display BUFFER in a side window of the selected frame. |
| @@ -906,9 +971,27 @@ following special symbols can be used in ALIST. | |||
| 906 | the specified side. A negative value means use a slot | 971 | the specified side. A negative value means use a slot |
| 907 | preceding (that is, above or on the left of) the middle slot. | 972 | preceding (that is, above or on the left of) the middle slot. |
| 908 | A positive value means use a slot following (that is, below or | 973 | A positive value means use a slot following (that is, below or |
| 909 | on the right of) the middle slot. The default is zero." | 974 | on the right of) the middle slot. The default is zero. |
| 910 | (let ((side (or (cdr (assq 'side alist)) 'bottom)) | 975 | |
| 911 | (slot (or (cdr (assq 'slot alist)) 0))) | 976 | If the current frame size or the settings of `window-sides-slots' |
| 977 | do not permit making a new window, a suitable existing window may | ||
| 978 | be reused and have its `window-slot' parameter value accordingly | ||
| 979 | modified. | ||
| 980 | |||
| 981 | Unless `display-buffer-mark-dedicated' is non-nil, softly | ||
| 982 | dedicate the side window used to BUFFER. Return nil if no | ||
| 983 | suitable window is found. | ||
| 984 | |||
| 985 | This function installs the `window-side' and `window-slot' | ||
| 986 | parameters and makes them persistent. It neither modifies ALIST | ||
| 987 | nor installs any other window parameters unless they have been | ||
| 988 | explicitly provided via a `window-parameter' entry in ALIST." | ||
| 989 | (let* ((side (or (cdr (assq 'side alist)) 'bottom)) | ||
| 990 | (slot (or (cdr (assq 'slot alist)) 0)) | ||
| 991 | (left-or-right (memq side '(left right))) | ||
| 992 | ;; Softly dedicate window to BUFFER unless | ||
| 993 | ;; `display-buffer-mark-dedicated' already asks for it. | ||
| 994 | (dedicated (or display-buffer-mark-dedicated 'side))) | ||
| 912 | (cond | 995 | (cond |
| 913 | ((not (memq side '(top bottom left right))) | 996 | ((not (memq side '(top bottom left right))) |
| 914 | (error "Invalid side %s specified" side)) | 997 | (error "Invalid side %s specified" side)) |
| @@ -918,15 +1001,20 @@ following special symbols can be used in ALIST. | |||
| 918 | (let* ((major (window-with-parameter 'window-side side nil t)) | 1001 | (let* ((major (window-with-parameter 'window-side side nil t)) |
| 919 | ;; `major' is the major window on SIDE, `windows' the list of | 1002 | ;; `major' is the major window on SIDE, `windows' the list of |
| 920 | ;; life windows on SIDE. | 1003 | ;; life windows on SIDE. |
| 921 | (windows | 1004 | (reversed (window--sides-reverse-on-frame-p (selected-frame))) |
| 922 | (when major | 1005 | (windows |
| 923 | (let (windows) | 1006 | (cond |
| 924 | (walk-window-tree | 1007 | ((window-live-p major) |
| 925 | (lambda (window) | 1008 | (list major)) |
| 926 | (when (eq (window-parameter window 'window-side) side) | 1009 | ((window-valid-p major) |
| 927 | (setq windows (cons window windows)))) | 1010 | (let* ((first (window-child major)) |
| 928 | nil nil 'nomini) | 1011 | (next (window-next-sibling first)) |
| 929 | (nreverse windows)))) | 1012 | (windows (list next first))) |
| 1013 | (setq reversed (> (window-parameter first 'window-slot) | ||
| 1014 | (window-parameter next 'window-slot))) | ||
| 1015 | (while (setq next (window-next-sibling next)) | ||
| 1016 | (setq windows (cons next windows))) | ||
| 1017 | (if reversed windows (nreverse windows)))))) | ||
| 930 | (slots (when major (max 1 (window-child-count major)))) | 1018 | (slots (when major (max 1 (window-child-count major)))) |
| 931 | (max-slots | 1019 | (max-slots |
| 932 | (nth (cond | 1020 | (nth (cond |
| @@ -935,17 +1023,18 @@ following special symbols can be used in ALIST. | |||
| 935 | ((eq side 'right) 2) | 1023 | ((eq side 'right) 2) |
| 936 | ((eq side 'bottom) 3)) | 1024 | ((eq side 'bottom) 3)) |
| 937 | window-sides-slots)) | 1025 | window-sides-slots)) |
| 1026 | (window--sides-inhibit-check t) | ||
| 938 | window this-window this-slot prev-window next-window | 1027 | window this-window this-slot prev-window next-window |
| 939 | best-window best-slot abs-slot) | 1028 | best-window best-slot abs-slot) |
| 940 | 1029 | ||
| 941 | (cond | 1030 | (cond |
| 942 | ((and (numberp max-slots) (<= max-slots 0)) | 1031 | ((and (numberp max-slots) (<= max-slots 0)) |
| 943 | ;; No side-slots available on this side. Don't create an error, | 1032 | ;; No side-slots available on this side. Don't raise an error, |
| 944 | ;; just return nil. | 1033 | ;; just return nil. |
| 945 | nil) | 1034 | nil) |
| 946 | ((not windows) | 1035 | ((not windows) |
| 947 | ;; No major window exists on this side, make one. | 1036 | ;; No major side window exists on this side, make one. |
| 948 | (display-buffer-in-major-side-window buffer side slot alist)) | 1037 | (window--make-major-side-window buffer side slot alist)) |
| 949 | (t | 1038 | (t |
| 950 | ;; Scan windows on SIDE. | 1039 | ;; Scan windows on SIDE. |
| 951 | (catch 'found | 1040 | (catch 'found |
| @@ -953,7 +1042,7 @@ following special symbols can be used in ALIST. | |||
| 953 | (setq this-slot (window-parameter window 'window-slot)) | 1042 | (setq this-slot (window-parameter window 'window-slot)) |
| 954 | (cond | 1043 | (cond |
| 955 | ;; The following should not happen and probably be checked | 1044 | ;; The following should not happen and probably be checked |
| 956 | ;; by window--side-check. | 1045 | ;; by window--sides-check. |
| 957 | ((not (numberp this-slot))) | 1046 | ((not (numberp this-slot))) |
| 958 | ((= this-slot slot) | 1047 | ((= this-slot slot) |
| 959 | ;; A window with a matching slot has been found. | 1048 | ;; A window with a matching slot has been found. |
| @@ -970,131 +1059,241 @@ following special symbols can be used in ALIST. | |||
| 970 | (unless (and best-slot (<= best-slot abs-slot)) | 1059 | (unless (and best-slot (<= best-slot abs-slot)) |
| 971 | (setq best-window window) | 1060 | (setq best-window window) |
| 972 | (setq best-slot abs-slot)) | 1061 | (setq best-slot abs-slot)) |
| 973 | (cond | 1062 | (if reversed |
| 974 | ((<= this-slot slot) | 1063 | (cond |
| 975 | (setq prev-window window)) | 1064 | ((<= this-slot slot) |
| 976 | ((not next-window) | 1065 | (setq next-window window)) |
| 977 | (setq next-window window))))))) | 1066 | ((not prev-window) |
| 978 | 1067 | (setq prev-window window))) | |
| 979 | ;; `this-window' is the first window with the same SLOT. | 1068 | (cond |
| 1069 | ((<= this-slot slot) | ||
| 1070 | (setq prev-window window)) | ||
| 1071 | ((not next-window) | ||
| 1072 | (setq next-window window)))))))) | ||
| 1073 | |||
| 1074 | ;; `this-window' is the first window with the same SLOT. | ||
| 980 | ;; `prev-window' is the window with the largest slot < SLOT. A new | 1075 | ;; `prev-window' is the window with the largest slot < SLOT. A new |
| 981 | ;; window will be created after it. | 1076 | ;; window will be created after it. |
| 982 | ;; `next-window' is the window with the smallest slot > SLOT. A new | 1077 | ;; `next-window' is the window with the smallest slot > SLOT. A new |
| 983 | ;; window will be created before it. | 1078 | ;; window will be created before it. |
| 984 | ;; `best-window' is the window with the smallest absolute difference | 1079 | ;; `best-window' is the window with the smallest absolute difference |
| 985 | ;; of its slot and SLOT. | 1080 | ;; of its slot and SLOT. |
| 986 | |||
| 987 | ;; Note: We dedicate the window used softly to its buffer to | ||
| 988 | ;; avoid that "other" (non-side) buffer display functions steal | ||
| 989 | ;; it from us. This must eventually become customizable via | ||
| 990 | ;; ALIST (or, better, avoided in the "other" functions). | ||
| 991 | (or (and this-window | 1081 | (or (and this-window |
| 992 | ;; Reuse `this-window'. | 1082 | ;; Reuse `this-window'. |
| 993 | (window--display-buffer buffer this-window 'reuse alist 'side)) | 1083 | (with-current-buffer buffer |
| 1084 | (setq window--sides-shown t)) | ||
| 1085 | (window--display-buffer | ||
| 1086 | buffer this-window 'reuse alist dedicated)) | ||
| 994 | (and (or (not max-slots) (< slots max-slots)) | 1087 | (and (or (not max-slots) (< slots max-slots)) |
| 995 | (or (and next-window | 1088 | (or (and next-window |
| 996 | ;; Make new window before `next-window'. | 1089 | ;; Make new window before `next-window'. |
| 997 | (let ((next-side | 1090 | (let ((next-side (if left-or-right 'above 'left)) |
| 998 | (if (memq side '(left right)) 'above 'left)) | ||
| 999 | (window-combination-resize 'side)) | 1091 | (window-combination-resize 'side)) |
| 1000 | (setq window (split-window next-window nil next-side)) | 1092 | (setq window (split-window-no-error |
| 1001 | ;; When the new window is deleted, its space | 1093 | next-window nil next-side)))) |
| 1002 | ;; is returned to other side windows. | ||
| 1003 | (set-window-parameter | ||
| 1004 | window 'delete-window 'delete-side-window) | ||
| 1005 | window)) | ||
| 1006 | (and prev-window | 1094 | (and prev-window |
| 1007 | ;; Make new window after `prev-window'. | 1095 | ;; Make new window after `prev-window'. |
| 1008 | (let ((prev-side | 1096 | (let ((prev-side (if left-or-right 'below 'right)) |
| 1009 | (if (memq side '(left right)) 'below 'right)) | ||
| 1010 | (window-combination-resize 'side)) | 1097 | (window-combination-resize 'side)) |
| 1011 | (setq window (split-window prev-window nil prev-side)) | 1098 | (setq window (split-window-no-error |
| 1012 | ;; When the new window is deleted, its space | 1099 | prev-window nil prev-side))))) |
| 1013 | ;; is returned to other side windows. | ||
| 1014 | (set-window-parameter | ||
| 1015 | window 'delete-window 'delete-side-window) | ||
| 1016 | window))) | ||
| 1017 | (set-window-parameter window 'window-slot slot) | 1100 | (set-window-parameter window 'window-slot slot) |
| 1018 | (window--display-buffer buffer window 'window alist 'side)) | 1101 | (with-current-buffer buffer |
| 1102 | (setq window--sides-shown t)) | ||
| 1103 | (window--display-buffer | ||
| 1104 | buffer window 'window alist dedicated)) | ||
| 1019 | (and best-window | 1105 | (and best-window |
| 1020 | ;; Reuse `best-window'. | 1106 | ;; Reuse `best-window'. |
| 1021 | (progn | 1107 | (progn |
| 1022 | ;; Give best-window the new slot value. | 1108 | ;; Give best-window the new slot value. |
| 1023 | (set-window-parameter best-window 'window-slot slot) | 1109 | (set-window-parameter best-window 'window-slot slot) |
| 1024 | (window--display-buffer | 1110 | (with-current-buffer buffer |
| 1025 | buffer best-window 'reuse alist 'side))))))))) | 1111 | (setq window--sides-shown t)) |
| 1026 | 1112 | (window--display-buffer | |
| 1027 | (defun window--side-check (&optional frame) | 1113 | buffer best-window 'reuse alist dedicated))))))))) |
| 1028 | "Check the side window configuration of FRAME. | 1114 | |
| 1029 | FRAME defaults to the selected frame. | 1115 | (defun window-toggle-side-windows (&optional frame) |
| 1030 | 1116 | "Toggle side windows on specified FRAME. | |
| 1031 | A valid side window configuration preserves the following two | 1117 | FRAME must be a live frame and defaults to the selected one. |
| 1032 | invariants: | 1118 | |
| 1033 | 1119 | If FRAME has at least one side window, save FRAME's state in the | |
| 1034 | - If there exists a window whose window-side parameter is | 1120 | FRAME's `window-state' frame parameter and delete all side |
| 1035 | non-nil, there must exist at least one live window whose | 1121 | windows on FRAME afterwards. Otherwise, if FRAME has a |
| 1036 | window-side parameter is nil. | 1122 | `window-state' parameter, use that to restore any side windows on |
| 1037 | 1123 | FRAME leaving FRAME's main window alone. Signal an error if | |
| 1038 | - If a window W has a non-nil window-side parameter (i) it must | 1124 | FRAME has no side window and no saved state is found." |
| 1039 | have a parent window and that parent's window-side parameter | 1125 | (interactive) |
| 1040 | must be either nil or the same as for W, and (ii) any child | 1126 | (let* ((frame (window-normalize-frame frame)) |
| 1041 | window of W must have the same window-side parameter as W. | 1127 | (window--sides-inhibit-check t) |
| 1042 | 1128 | state) | |
| 1043 | If the configuration is invalid, reset the window-side parameters | 1129 | (cond |
| 1044 | of all windows on FRAME to nil." | 1130 | ((window-with-parameter 'window-side nil frame) |
| 1045 | (let (left top right bottom none side parent parent-side) | 1131 | ;; At least one side window exists. Remove all side windows after |
| 1046 | (when (or (catch 'reset | 1132 | ;; saving FRAME's state in its `window-state' parameter. |
| 1047 | (walk-window-tree | 1133 | (set-frame-parameter |
| 1048 | (lambda (window) | 1134 | frame 'window-state (window-state-get (frame-root-window frame))) |
| 1049 | (setq side (window-parameter window 'window-side)) | 1135 | (let ((ignore-window-parameters t)) |
| 1050 | (setq parent (window-parent window)) | 1136 | (delete-other-windows (window-main-window frame)))) |
| 1051 | (setq parent-side | 1137 | ((setq state (frame-parameter frame 'window-state)) |
| 1052 | (and parent (window-parameter parent 'window-side))) | 1138 | ;; A window state was saved for FRAME. Restore it and put the |
| 1053 | ;; The following `cond' seems a bit tedious, but I'd | 1139 | ;; current root window into its main window. |
| 1054 | ;; rather stick to using just the stack. | 1140 | (let ((main-state (window-state-get (frame-root-window frame)))) |
| 1055 | (cond | 1141 | (window-state-put state (frame-root-window frame) t) |
| 1056 | (parent-side | 1142 | (window-state-put main-state (window-main-window frame))) |
| 1057 | (when (not (eq parent-side side)) | 1143 | (window--sides-reverse-frame frame)) |
| 1058 | ;; A parent whose window-side is non-nil must | 1144 | (t |
| 1059 | ;; have a child with the same window-side. | 1145 | (error "No side windows state found"))))) |
| 1060 | (throw 'reset t))) | 1146 | |
| 1061 | ((not side) | 1147 | (defun window--sides-reverse-all () |
| 1062 | (when (window-buffer window) | 1148 | "Maybe reverse side windows on all frames." |
| 1063 | ;; Record that we have at least one non-side, | 1149 | (unless window--sides-inhibit-check |
| 1064 | ;; live window. | 1150 | (dolist (frame (frame-list)) |
| 1065 | (setq none t))) | 1151 | (window--sides-reverse-frame frame)))) |
| 1066 | ((if (memq side '(left top)) | 1152 | |
| 1067 | (window-prev-sibling window) | 1153 | (defun window--sides-reverse-frame (frame) |
| 1068 | (window-next-sibling window)) | 1154 | "Maybe reverse side windows on FRAME." |
| 1069 | ;; Left and top major side windows must not have a | 1155 | (when (eq window-sides-reversed 'bidi) |
| 1070 | ;; previous sibling, right and bottom major side | 1156 | (let ((window (frame-selected-window frame))) |
| 1071 | ;; windows must not have a next sibling. | 1157 | (unless (or (window-parameter window 'window-side) |
| 1072 | (throw 'reset t)) | 1158 | (window-minibuffer-p window)) |
| 1073 | ;; Now check that there's no more than one major | 1159 | (set-frame-parameter |
| 1074 | ;; window for any of left, top, right and bottom. | 1160 | frame 'window-sides-main-selected-window window)))) |
| 1075 | ((eq side 'left) | 1161 | (window--sides-reverse-side frame 'top) |
| 1076 | (if left (throw 'reset t) (setq left t))) | 1162 | (window--sides-reverse-side frame 'bottom)) |
| 1077 | ((eq side 'top) | 1163 | |
| 1078 | (if top (throw 'reset t) (setq top t))) | 1164 | (defun window--sides-reverse-side (frame side) |
| 1079 | ((eq side 'right) | 1165 | "Maybe reverse windows on SIDE of FRAME." |
| 1080 | (if right (throw 'reset t) (setq right t))) | 1166 | (let ((major (window-with-parameter 'window-side side frame t)) |
| 1081 | ((eq side 'bottom) | 1167 | (window--sides-inhibit-check t)) |
| 1082 | (if bottom (throw 'reset t) (setq bottom t))) | 1168 | (when (and major (not (window-live-p major))) |
| 1083 | (t | 1169 | (let* ((first (window-child major)) |
| 1084 | (throw 'reset t)))) | 1170 | (reversed (> (window-parameter first 'window-slot) |
| 1085 | frame t 'nomini)) | 1171 | (window-parameter |
| 1086 | ;; If there's a side window, there must be at least one | 1172 | (window-next-sibling first) 'window-slot))) |
| 1087 | ;; non-side window. | 1173 | (reverse (window--sides-reverse-on-frame-p frame))) |
| 1088 | (and (or left top right bottom) (not none))) | 1174 | (unless (eq reversed reverse) |
| 1089 | (walk-window-tree | 1175 | ;; We have to reverse. |
| 1090 | (lambda (window) | 1176 | (let ((last (window-last-child major))) |
| 1091 | (set-window-parameter window 'window-side nil)) | 1177 | (while (and (not (eq first last)) |
| 1092 | frame t 'nomini)))) | 1178 | (not (eq first (window-next-sibling last)))) |
| 1179 | (window-swap-states first last t) | ||
| 1180 | (setq first (window-next-sibling first)) | ||
| 1181 | (setq last (window-prev-sibling last))))))))) | ||
| 1182 | |||
| 1183 | (defun window--sides-reverse (symbol value) | ||
| 1184 | "Helper function for customizing `window-sides-reversed'." | ||
| 1185 | (set-default symbol value) | ||
| 1186 | (remove-hook 'buffer-list-update-hook 'window--sides-reverse-all) | ||
| 1187 | (remove-hook 'window-configuration-change-hook 'window--sides-reverse-all) | ||
| 1188 | (dolist (frame (frame-list)) | ||
| 1189 | (set-frame-parameter frame 'window-sides-main-selected-window nil)) | ||
| 1190 | (when (eq value 'bidi) | ||
| 1191 | (add-hook 'buffer-list-update-hook 'window--sides-reverse-all) | ||
| 1192 | (add-hook 'window-configuration-change-hook 'window--sides-reverse-all)) | ||
| 1193 | (window--sides-reverse-all)) | ||
| 1194 | |||
| 1195 | (defun window--sides-verticalize-frame (&optional frame) | ||
| 1196 | "Maybe change side windows layout on specified FRAME." | ||
| 1197 | (setq frame (window-normalize-frame frame)) | ||
| 1198 | (let ((window--sides-inhibit-check t) | ||
| 1199 | (root (frame-root-window frame)) | ||
| 1200 | (main (window-main-window frame))) | ||
| 1201 | (when (and (not (eq main root)) | ||
| 1202 | (not (eq (window-parent main) root)) | ||
| 1203 | (window-combined-p main window-sides-vertical)) | ||
| 1204 | (let* ((window--sides-inhibit-check t) | ||
| 1205 | (ignore-window-parameters t) | ||
| 1206 | (first (window-child root)) | ||
| 1207 | (first-state | ||
| 1208 | (and first (window-parameter first 'window-side) | ||
| 1209 | (window-state-get first))) | ||
| 1210 | (last (window-last-child root)) | ||
| 1211 | (last-state | ||
| 1212 | (and last (window-parameter last 'window-side) | ||
| 1213 | (window-state-get last))) | ||
| 1214 | (dummy (get-buffer-create " *dummy*")) | ||
| 1215 | major) | ||
| 1216 | (unwind-protect | ||
| 1217 | (progn | ||
| 1218 | (when first-state (delete-window first)) | ||
| 1219 | (when last-state (delete-window last)) | ||
| 1220 | (when first-state | ||
| 1221 | (setq major (window--make-major-side-window | ||
| 1222 | dummy (if window-sides-vertical 'top 'left) 0)) | ||
| 1223 | (window-state-put first-state major t)) | ||
| 1224 | (when last-state | ||
| 1225 | (setq major (window--make-major-side-window | ||
| 1226 | dummy (if window-sides-vertical 'bottom 'right) 0)) | ||
| 1227 | (window-state-put last-state major t))) | ||
| 1228 | (kill-buffer " *dummy*")))))) | ||
| 1229 | |||
| 1230 | (defun window--sides-verticalize (symbol value) | ||
| 1231 | "Helper function for customizing `window-sides-vertical'." | ||
| 1232 | (set-default symbol value) | ||
| 1233 | (dolist (frame (frame-list)) | ||
| 1234 | (window--sides-verticalize-frame frame))) | ||
| 1235 | |||
| 1236 | (defun window--sides-check-failed (frame) | ||
| 1237 | "Helper function for `window--sides-check'." | ||
| 1238 | (catch 'failed | ||
| 1239 | ;; FRAME must have a main window. | ||
| 1240 | (unless (window-main-window frame) | ||
| 1241 | (error "Frame %s has no main window" frame) | ||
| 1242 | (throw 'failed t)) | ||
| 1243 | ;; Now check the side windows. | ||
| 1244 | (dolist (side '(left top right bottom)) | ||
| 1245 | (let ((window (window-with-parameter 'window-side side frame t))) | ||
| 1246 | (when window | ||
| 1247 | ;; If WINDOW is live there must be no other window on this frame | ||
| 1248 | ;; with the same `window-side' parameter. | ||
| 1249 | (if (window-live-p window) | ||
| 1250 | (walk-window-tree | ||
| 1251 | (lambda (this) | ||
| 1252 | (when (and (eq (window-parameter this 'window-side) side) | ||
| 1253 | (not (eq this window))) | ||
| 1254 | (error "Window %s has same side %s as window %s but no common parent" | ||
| 1255 | this side window) | ||
| 1256 | (throw 'failed t))) | ||
| 1257 | frame t 'nomini) | ||
| 1258 | (walk-window-tree | ||
| 1259 | (lambda (this) | ||
| 1260 | (if (eq (window-parent this) window) | ||
| 1261 | (unless (eq (window-parameter this 'window-side) side) | ||
| 1262 | (error "Window %s has not same side %s as its parent %s" | ||
| 1263 | this side window) | ||
| 1264 | (throw 'failed t)) | ||
| 1265 | (when (and (eq (window-parameter this 'window-side) side) | ||
| 1266 | (not (eq this window))) | ||
| 1267 | (error "Window %s has same side %s as major side window %s but its parent is %s" | ||
| 1268 | this side window (window-parent this)) | ||
| 1269 | (throw 'failed t)))) | ||
| 1270 | frame t 'nomini))))))) | ||
| 1271 | |||
| 1272 | (defun window--sides-check (frame) | ||
| 1273 | "Check side windows configuration of FRAME. | ||
| 1274 | In a valid side windows configuration there can be at most one | ||
| 1275 | internal side window on each side and all its children must be | ||
| 1276 | live and have the same `window-side' parameter and no other | ||
| 1277 | window with the same `window-side' parameter exists on FRAME. If | ||
| 1278 | there is no such internal window, there may be at most one window | ||
| 1279 | with this side's `window-side' parameter on FRAME. | ||
| 1280 | |||
| 1281 | If the configuration is invalid, reset the `window-side' | ||
| 1282 | parameters of all windows on FRAME." | ||
| 1283 | (when (and (not window--sides-inhibit-check) | ||
| 1284 | (window-with-parameter 'window-side nil frame t) | ||
| 1285 | (window--sides-check-failed frame)) | ||
| 1286 | ;; Reset all `window-side' parameters. | ||
| 1287 | (walk-window-tree | ||
| 1288 | (lambda (window) | ||
| 1289 | (set-window-parameter window 'window-side nil)) | ||
| 1290 | frame t 'nomini) | ||
| 1291 | (message "Side windows configuration reset for frame %s" frame))) | ||
| 1093 | 1292 | ||
| 1094 | (defun window--check (&optional frame) | 1293 | (defun window--check (&optional frame) |
| 1095 | "Check atomic and side windows on FRAME. | 1294 | "Check atomic and side windows on FRAME. |
| 1096 | FRAME defaults to the selected frame." | 1295 | FRAME defaults to the selected frame." |
| 1097 | (window--side-check frame) | 1296 | (window--sides-check frame) |
| 1098 | (window--atom-check frame)) | 1297 | (window--atom-check frame)) |
| 1099 | 1298 | ||
| 1100 | ;; Dumping frame/window contents. | 1299 | ;; Dumping frame/window contents. |
| @@ -2631,10 +2830,7 @@ instead." | |||
| 2631 | "Resize WINDOW vertically if it is resizable by DELTA lines. | 2830 | "Resize WINDOW vertically if it is resizable by DELTA lines. |
| 2632 | This function is like `window-resize' but does not signal an | 2831 | This function is like `window-resize' but does not signal an |
| 2633 | error when WINDOW cannot be resized. For the meaning of the | 2832 | error when WINDOW cannot be resized. For the meaning of the |
| 2634 | optional arguments see the documentation of `window-resize'. | 2833 | optional arguments see the documentation of `window-resize'." |
| 2635 | |||
| 2636 | Optional argument PIXELWISE non-nil means interpret DELTA as | ||
| 2637 | pixels." | ||
| 2638 | (when (window--resizable-p | 2834 | (when (window--resizable-p |
| 2639 | window delta horizontal ignore nil nil nil pixelwise) | 2835 | window delta horizontal ignore nil nil nil pixelwise) |
| 2640 | (window-resize window delta horizontal ignore pixelwise))) | 2836 | (window-resize window delta horizontal ignore pixelwise))) |
| @@ -3224,8 +3420,10 @@ move it as far as possible in the desired direction." | |||
| 3224 | (setq left first-left) | 3420 | (setq left first-left) |
| 3225 | (while (and left | 3421 | (while (and left |
| 3226 | (or (window-size-fixed-p left horizontal 'preserved) | 3422 | (or (window-size-fixed-p left horizontal 'preserved) |
| 3227 | (<= (window-size left horizontal t) | 3423 | (and (< delta 0) |
| 3228 | (window-min-size left horizontal 'preserved t)))) | 3424 | (<= (window-size left horizontal t) |
| 3425 | (window-min-size | ||
| 3426 | left horizontal 'preserved t))))) | ||
| 3229 | (setq left | 3427 | (setq left |
| 3230 | (or (window-left left) | 3428 | (or (window-left left) |
| 3231 | (progn | 3429 | (progn |
| @@ -3245,7 +3443,8 @@ move it as far as possible in the desired direction." | |||
| 3245 | (or (window-size-fixed-p right horizontal) | 3443 | (or (window-size-fixed-p right horizontal) |
| 3246 | (and (> delta 0) | 3444 | (and (> delta 0) |
| 3247 | (<= (window-size right horizontal t) | 3445 | (<= (window-size right horizontal t) |
| 3248 | (window-min-size right horizontal 'preserved t))))) | 3446 | (window-min-size |
| 3447 | right horizontal 'preserved t))))) | ||
| 3249 | (setq right | 3448 | (setq right |
| 3250 | (or (window-right right) | 3449 | (or (window-right right) |
| 3251 | (progn | 3450 | (progn |
| @@ -3259,8 +3458,10 @@ move it as far as possible in the desired direction." | |||
| 3259 | (setq right first-right) | 3458 | (setq right first-right) |
| 3260 | (while (and right | 3459 | (while (and right |
| 3261 | (or (window-size-fixed-p right horizontal 'preserved) | 3460 | (or (window-size-fixed-p right horizontal 'preserved) |
| 3262 | (<= (window-size right horizontal t) | 3461 | (and (> delta 0) |
| 3263 | (window-min-size right horizontal 'preserved t)))) | 3462 | (<= (window-size right horizontal t) |
| 3463 | (window-min-size | ||
| 3464 | right horizontal 'preserved t))))) | ||
| 3264 | (setq right | 3465 | (setq right |
| 3265 | (or (window-right right) | 3466 | (or (window-right right) |
| 3266 | (progn | 3467 | (progn |
| @@ -3289,8 +3490,9 @@ move it as far as possible in the desired direction." | |||
| 3289 | ;; Start resizing. | 3490 | ;; Start resizing. |
| 3290 | (window--resize-reset frame horizontal) | 3491 | (window--resize-reset frame horizontal) |
| 3291 | ;; Try to enlarge LEFT first. | 3492 | ;; Try to enlarge LEFT first. |
| 3292 | (setq this-delta (window--resizable | 3493 | (setq this-delta |
| 3293 | left delta horizontal ignore 'after nil nil pixelwise)) | 3494 | (window--resizable |
| 3495 | left delta horizontal ignore 'after nil nil pixelwise)) | ||
| 3294 | (unless (zerop this-delta) | 3496 | (unless (zerop this-delta) |
| 3295 | (window--resize-this-window | 3497 | (window--resize-this-window |
| 3296 | left this-delta horizontal ignore t 'before | 3498 | left this-delta horizontal ignore t 'before |
| @@ -3740,7 +3942,9 @@ and no others." | |||
| 3740 | (defun window-deletable-p (&optional window) | 3942 | (defun window-deletable-p (&optional window) |
| 3741 | "Return t if WINDOW can be safely deleted from its frame. | 3943 | "Return t if WINDOW can be safely deleted from its frame. |
| 3742 | WINDOW must be a valid window and defaults to the selected one. | 3944 | WINDOW must be a valid window and defaults to the selected one. |
| 3743 | Return `frame' if deleting WINDOW should also delete its frame." | 3945 | |
| 3946 | Return `frame' if WINDOW is the root window of its frame and that | ||
| 3947 | frame can be safely deleted." | ||
| 3744 | (setq window (window-normalize-window window)) | 3948 | (setq window (window-normalize-window window)) |
| 3745 | 3949 | ||
| 3746 | (unless (or ignore-window-parameters | 3950 | (unless (or ignore-window-parameters |
| @@ -3767,10 +3971,14 @@ Return `frame' if deleting WINDOW should also delete its frame." | |||
| 3767 | (let ((minibuf (active-minibuffer-window))) | 3971 | (let ((minibuf (active-minibuffer-window))) |
| 3768 | (and minibuf (eq frame (window-frame minibuf))))) | 3972 | (and minibuf (eq frame (window-frame minibuf))))) |
| 3769 | 'frame)) | 3973 | 'frame)) |
| 3974 | ((window-minibuffer-p window) | ||
| 3975 | ;; If WINDOW is the minibuffer window of a non-minibuffer-only | ||
| 3976 | ;; frame, it cannot be deleted separately. | ||
| 3977 | nil) | ||
| 3770 | ((or ignore-window-parameters | 3978 | ((or ignore-window-parameters |
| 3771 | (not (eq window (window--major-non-side-window frame)))) | 3979 | (not (eq window (window-main-window frame)))) |
| 3772 | ;; WINDOW can be deleted unless it is the major non-side window of | 3980 | ;; Otherwise, WINDOW can be deleted unless it is the main window |
| 3773 | ;; its frame. | 3981 | ;; of its frame. |
| 3774 | t)))) | 3982 | t)))) |
| 3775 | 3983 | ||
| 3776 | (defun window--in-subtree-p (window root) | 3984 | (defun window--in-subtree-p (window root) |
| @@ -3826,11 +4034,14 @@ that is its frame's root window." | |||
| 3826 | (throw 'done (delete-window atom-root)))) | 4034 | (throw 'done (delete-window atom-root)))) |
| 3827 | ((not parent) | 4035 | ((not parent) |
| 3828 | (error "Attempt to delete minibuffer or sole ordinary window")) | 4036 | (error "Attempt to delete minibuffer or sole ordinary window")) |
| 3829 | ((eq window (window--major-non-side-window frame)) | 4037 | ((eq window (window-main-window frame)) |
| 3830 | (error "Attempt to delete last non-side window"))) | 4038 | (error "Attempt to delete main window of frame %s" frame))) |
| 3831 | 4039 | ||
| 3832 | (let* ((horizontal (window-left-child parent)) | 4040 | (let* ((horizontal (window-left-child parent)) |
| 3833 | (size (window-size window horizontal t)) | 4041 | (size (window-size window horizontal t)) |
| 4042 | (window-combination-resize | ||
| 4043 | (or window-combination-resize | ||
| 4044 | (window-parameter parent 'window-side))) | ||
| 3834 | (frame-selected | 4045 | (frame-selected |
| 3835 | (window--in-subtree-p (frame-selected-window frame) window)) | 4046 | (window--in-subtree-p (frame-selected-window frame) window)) |
| 3836 | ;; Emacs 23 preferably gives WINDOW's space to its left | 4047 | ;; Emacs 23 preferably gives WINDOW's space to its left |
| @@ -3886,8 +4097,7 @@ window signal an error." | |||
| 3886 | (setq window (window-normalize-window window)) | 4097 | (setq window (window-normalize-window window)) |
| 3887 | (let* ((frame (window-frame window)) | 4098 | (let* ((frame (window-frame window)) |
| 3888 | (function (window-parameter window 'delete-other-windows)) | 4099 | (function (window-parameter window 'delete-other-windows)) |
| 3889 | (window-side (window-parameter window 'window-side)) | 4100 | atom-root main) |
| 3890 | atom-root side-main) | ||
| 3891 | (window--check frame) | 4101 | (window--check frame) |
| 3892 | (catch 'done | 4102 | (catch 'done |
| 3893 | (cond | 4103 | (cond |
| @@ -3905,18 +4115,48 @@ window signal an error." | |||
| 3905 | (if (eq atom-root (frame-root-window frame)) | 4115 | (if (eq atom-root (frame-root-window frame)) |
| 3906 | (error "Root of atomic window is root window of its frame") | 4116 | (error "Root of atomic window is root window of its frame") |
| 3907 | (throw 'done (delete-other-windows atom-root)))) | 4117 | (throw 'done (delete-other-windows atom-root)))) |
| 3908 | ((memq window-side window-sides) | 4118 | ((window-parameter window 'window-side) |
| 3909 | (error "Cannot make side window the only window")) | 4119 | (error "Cannot make side window the only window")) |
| 3910 | ((and (window-minibuffer-p window) | 4120 | ((and (window-minibuffer-p window) |
| 3911 | (not (eq window (frame-root-window window)))) | 4121 | (not (eq window (frame-root-window window)))) |
| 3912 | (error "Can't expand minibuffer to full frame"))) | 4122 | (error "Can't expand minibuffer to full frame"))) |
| 3913 | 4123 | ||
| 3914 | ;; If WINDOW is the major non-side window, do nothing. | 4124 | (cond |
| 3915 | (if (window-with-parameter 'window-side) | 4125 | ((or ignore-window-parameters |
| 3916 | (setq side-main (window--major-non-side-window frame)) | 4126 | (not (window-with-parameter 'no-delete-other-window nil frame))) |
| 3917 | (setq side-main (frame-root-window frame))) | 4127 | (setq main (frame-root-window frame))) |
| 3918 | (unless (eq window side-main) | 4128 | ((catch 'tag |
| 3919 | (delete-other-windows-internal window side-main) | 4129 | (walk-window-tree |
| 4130 | (lambda (other) | ||
| 4131 | (when (or (and (window-parameter other 'window-side) | ||
| 4132 | (not (window-parameter | ||
| 4133 | other 'no-delete-other-window))) | ||
| 4134 | (and (not (window-parameter other 'window-side)) | ||
| 4135 | (window-parameter | ||
| 4136 | other 'no-delete-other-window))) | ||
| 4137 | (throw 'tag nil)))) | ||
| 4138 | t) | ||
| 4139 | (setq main (window-main-window frame))) | ||
| 4140 | (t | ||
| 4141 | ;; Delete other windows via `delete-window' because either a | ||
| 4142 | ;; side window is or a non-side-window is not deletable. | ||
| 4143 | (dolist (other (window-list frame)) | ||
| 4144 | (when (and (window-live-p other) | ||
| 4145 | (not (eq other window)) | ||
| 4146 | (not (window-parameter | ||
| 4147 | other 'no-delete-other-window)) | ||
| 4148 | ;; When WINDOW and the other window are part of the | ||
| 4149 | ;; same atomic window, don't delete the other. | ||
| 4150 | (or (not atom-root) | ||
| 4151 | (not (eq (window-atom-root other) atom-root)))) | ||
| 4152 | (condition-case nil | ||
| 4153 | (delete-window other) | ||
| 4154 | (error nil)))) | ||
| 4155 | (throw 'done nil))) | ||
| 4156 | |||
| 4157 | ;; If WINDOW is the main window of its frame do nothing. | ||
| 4158 | (unless (eq window main) | ||
| 4159 | (delete-other-windows-internal window main) | ||
| 3920 | (run-window-configuration-change-hook frame) | 4160 | (run-window-configuration-change-hook frame) |
| 3921 | (window--check frame)) | 4161 | (window--check frame)) |
| 3922 | ;; Always return nil. | 4162 | ;; Always return nil. |
| @@ -4066,6 +4306,7 @@ to it." | |||
| 4066 | (interactive) | 4306 | (interactive) |
| 4067 | (let* ((window (window-normalize-window window t)) | 4307 | (let* ((window (window-normalize-window window t)) |
| 4068 | (frame (window-frame window)) | 4308 | (frame (window-frame window)) |
| 4309 | (window-side (window-parameter window 'window-side)) | ||
| 4069 | (old-buffer (window-buffer window)) | 4310 | (old-buffer (window-buffer window)) |
| 4070 | ;; Save this since it's destroyed by `set-window-buffer'. | 4311 | ;; Save this since it's destroyed by `set-window-buffer'. |
| 4071 | (next-buffers (window-next-buffers window)) | 4312 | (next-buffers (window-next-buffers window)) |
| @@ -4076,7 +4317,7 @@ to it." | |||
| 4076 | (unless (setq window (minibuffer-selected-window)) | 4317 | (unless (setq window (minibuffer-selected-window)) |
| 4077 | (error "Window %s is a minibuffer window" window))) | 4318 | (error "Window %s is a minibuffer window" window))) |
| 4078 | 4319 | ||
| 4079 | (when (window-dedicated-p window) | 4320 | (unless (memq (window-dedicated-p window) '(nil side)) |
| 4080 | ;; Don't switch in dedicated window. | 4321 | ;; Don't switch in dedicated window. |
| 4081 | (error "Window %s is dedicated to buffer %s" window old-buffer)) | 4322 | (error "Window %s is dedicated to buffer %s" window old-buffer)) |
| 4082 | 4323 | ||
| @@ -4106,23 +4347,27 @@ to it." | |||
| 4106 | ;; buffer we don't reverse the global buffer list to avoid showing | 4347 | ;; buffer we don't reverse the global buffer list to avoid showing |
| 4107 | ;; a buried buffer instead. Otherwise, we must reverse the global | 4348 | ;; a buried buffer instead. Otherwise, we must reverse the global |
| 4108 | ;; buffer list in order to make sure that switching to the | 4349 | ;; buffer list in order to make sure that switching to the |
| 4109 | ;; previous/next buffer traverse it in opposite directions. | 4350 | ;; previous/next buffer traverse it in opposite directions. Skip |
| 4110 | (dolist (buffer (if bury-or-kill | 4351 | ;; this step for side windows. |
| 4111 | (buffer-list frame) | 4352 | (unless window-side |
| 4112 | (nreverse (buffer-list frame)))) | 4353 | (dolist (buffer (if bury-or-kill |
| 4113 | (when (and (buffer-live-p buffer) | 4354 | (buffer-list frame) |
| 4114 | (not (eq buffer old-buffer)) | 4355 | (nreverse (buffer-list frame)))) |
| 4115 | (or (null pred) (funcall pred buffer)) | 4356 | (when (and (buffer-live-p buffer) |
| 4116 | (not (eq (aref (buffer-name buffer) 0) ?\s)) | 4357 | (not (eq buffer old-buffer)) |
| 4117 | (or bury-or-kill (not (memq buffer next-buffers)))) | 4358 | (or (null pred) (funcall pred buffer)) |
| 4118 | (if (and (not switch-to-visible-buffer) | 4359 | (not (eq (aref (buffer-name buffer) 0) ?\s)) |
| 4119 | (get-buffer-window buffer frame)) | 4360 | ;; Don't show a buffer shown in a side window before. |
| 4120 | ;; Try to avoid showing a buffer visible in some other window. | 4361 | (not (buffer-local-value 'window--sides-shown buffer)) |
| 4121 | (unless visible | 4362 | (or bury-or-kill (not (memq buffer next-buffers)))) |
| 4122 | (setq visible buffer)) | 4363 | (if (and (not switch-to-visible-buffer) |
| 4123 | (setq new-buffer buffer) | 4364 | (get-buffer-window buffer frame)) |
| 4124 | (set-window-buffer-start-and-point window new-buffer) | 4365 | ;; Try to avoid showing a buffer visible in some other window. |
| 4125 | (throw 'found t)))) | 4366 | (unless visible |
| 4367 | (setq visible buffer)) | ||
| 4368 | (setq new-buffer buffer) | ||
| 4369 | (set-window-buffer-start-and-point window new-buffer) | ||
| 4370 | (throw 'found t))))) | ||
| 4126 | (unless bury-or-kill | 4371 | (unless bury-or-kill |
| 4127 | ;; Scan reverted next buffers last (must not use nreverse | 4372 | ;; Scan reverted next buffers last (must not use nreverse |
| 4128 | ;; here!). | 4373 | ;; here!). |
| @@ -4184,6 +4429,7 @@ found." | |||
| 4184 | (interactive) | 4429 | (interactive) |
| 4185 | (let* ((window (window-normalize-window window t)) | 4430 | (let* ((window (window-normalize-window window t)) |
| 4186 | (frame (window-frame window)) | 4431 | (frame (window-frame window)) |
| 4432 | (window-side (window-parameter window 'window-side)) | ||
| 4187 | (old-buffer (window-buffer window)) | 4433 | (old-buffer (window-buffer window)) |
| 4188 | (next-buffers (window-next-buffers window)) | 4434 | (next-buffers (window-next-buffers window)) |
| 4189 | (pred (frame-parameter frame 'buffer-predicate)) | 4435 | (pred (frame-parameter frame 'buffer-predicate)) |
| @@ -4193,7 +4439,7 @@ found." | |||
| 4193 | (unless (setq window (minibuffer-selected-window)) | 4439 | (unless (setq window (minibuffer-selected-window)) |
| 4194 | (error "Window %s is a minibuffer window" window))) | 4440 | (error "Window %s is a minibuffer window" window))) |
| 4195 | 4441 | ||
| 4196 | (when (window-dedicated-p window) | 4442 | (unless (memq (window-dedicated-p window) '(nil side)) |
| 4197 | ;; Don't switch in dedicated window. | 4443 | ;; Don't switch in dedicated window. |
| 4198 | (error "Window %s is dedicated to buffer %s" window old-buffer)) | 4444 | (error "Window %s is dedicated to buffer %s" window old-buffer)) |
| 4199 | 4445 | ||
| @@ -4211,20 +4457,23 @@ found." | |||
| 4211 | window new-buffer (nth 1 entry) (nth 2 entry)) | 4457 | window new-buffer (nth 1 entry) (nth 2 entry)) |
| 4212 | (throw 'found t))) | 4458 | (throw 'found t))) |
| 4213 | ;; Scan the buffer list of WINDOW's frame next, skipping previous | 4459 | ;; Scan the buffer list of WINDOW's frame next, skipping previous |
| 4214 | ;; buffers entries. | 4460 | ;; buffers entries. Skip this step for side windows. |
| 4215 | (dolist (buffer (buffer-list frame)) | 4461 | (unless window-side |
| 4216 | (when (and (buffer-live-p buffer) | 4462 | (dolist (buffer (buffer-list frame)) |
| 4217 | (not (eq buffer old-buffer)) | 4463 | (when (and (buffer-live-p buffer) |
| 4218 | (or (null pred) (funcall pred buffer)) | 4464 | (not (eq buffer old-buffer)) |
| 4219 | (not (eq (aref (buffer-name buffer) 0) ?\s)) | 4465 | (or (null pred) (funcall pred buffer)) |
| 4220 | (not (assq buffer (window-prev-buffers window)))) | 4466 | (not (eq (aref (buffer-name buffer) 0) ?\s)) |
| 4221 | (if (and (not switch-to-visible-buffer) | 4467 | ;; Don't show a buffer shown in a side window before. |
| 4222 | (get-buffer-window buffer frame)) | 4468 | (not (buffer-local-value 'window--sides-shown buffer)) |
| 4223 | ;; Try to avoid showing a buffer visible in some other window. | 4469 | (not (assq buffer (window-prev-buffers window)))) |
| 4224 | (setq visible buffer) | 4470 | (if (and (not switch-to-visible-buffer) |
| 4225 | (setq new-buffer buffer) | 4471 | (get-buffer-window buffer frame)) |
| 4226 | (set-window-buffer-start-and-point window new-buffer) | 4472 | ;; Try to avoid showing a buffer visible in some other window. |
| 4227 | (throw 'found t)))) | 4473 | (setq visible buffer) |
| 4474 | (setq new-buffer buffer) | ||
| 4475 | (set-window-buffer-start-and-point window new-buffer) | ||
| 4476 | (throw 'found t))))) | ||
| 4228 | ;; Scan WINDOW's reverted previous buffers last (must not use | 4477 | ;; Scan WINDOW's reverted previous buffers last (must not use |
| 4229 | ;; nreverse here!) | 4478 | ;; nreverse here!) |
| 4230 | (dolist (entry (reverse (window-prev-buffers window))) | 4479 | (dolist (entry (reverse (window-prev-buffers window))) |
| @@ -4700,7 +4949,7 @@ frame. The selected window is not changed by this function." | |||
| 4700 | ;; side window, throw an error unless `window-combination-resize' | 4949 | ;; side window, throw an error unless `window-combination-resize' |
| 4701 | ;; equals 'side. | 4950 | ;; equals 'side. |
| 4702 | ((and (not (eq window-combination-resize 'side)) | 4951 | ((and (not (eq window-combination-resize 'side)) |
| 4703 | (window--side-window-p window)) | 4952 | (window-parameter window 'window-side)) |
| 4704 | (error "Cannot split side window or parent of side window")) | 4953 | (error "Cannot split side window or parent of side window")) |
| 4705 | ;; If `window-combination-resize' is 'side and window has a side | 4954 | ;; If `window-combination-resize' is 'side and window has a side |
| 4706 | ;; window sibling, bind `window-combination-limit' to t. | 4955 | ;; window sibling, bind `window-combination-limit' to t. |
| @@ -4894,6 +5143,17 @@ frame. The selected window is not changed by this function." | |||
| 4894 | ;; Always return the new window. | 5143 | ;; Always return the new window. |
| 4895 | new))))) | 5144 | new))))) |
| 4896 | 5145 | ||
| 5146 | (defun split-window-no-error (&optional window size side pixelwise) | ||
| 5147 | "Make a new window adjacent to WINDOW. | ||
| 5148 | This function is like `split-window' but does not signal an error | ||
| 5149 | when WINDOW cannot be split. | ||
| 5150 | |||
| 5151 | For the meaning of all arguments see the documentation of | ||
| 5152 | `split-window'." | ||
| 5153 | (condition-case nil | ||
| 5154 | (split-window window size side pixelwise) | ||
| 5155 | (error nil))) | ||
| 5156 | |||
| 4897 | ;; I think this should be the default; I think people will prefer it--rms. | 5157 | ;; I think this should be the default; I think people will prefer it--rms. |
| 4898 | (defcustom split-window-keep-point t | 5158 | (defcustom split-window-keep-point t |
| 4899 | "If non-nil, \\[split-window-below] preserves point in the new window. | 5159 | "If non-nil, \\[split-window-below] preserves point in the new window. |
| @@ -5286,12 +5546,17 @@ specific buffers." | |||
| 5286 | (scroll-bars . ,(window-scroll-bars window)) | 5546 | (scroll-bars . ,(window-scroll-bars window)) |
| 5287 | (vscroll . ,(window-vscroll window)) | 5547 | (vscroll . ,(window-vscroll window)) |
| 5288 | (dedicated . ,(window-dedicated-p window)) | 5548 | (dedicated . ,(window-dedicated-p window)) |
| 5289 | (point . ,(if writable point | 5549 | (point . ,(if writable |
| 5290 | (copy-marker point | 5550 | point |
| 5291 | (buffer-local-value | 5551 | (with-current-buffer buffer |
| 5292 | 'window-point-insertion-type | 5552 | (copy-marker point |
| 5293 | buffer)))) | 5553 | (buffer-local-value |
| 5294 | (start . ,(if writable start (copy-marker start))))))))) | 5554 | 'window-point-insertion-type |
| 5555 | buffer))))) | ||
| 5556 | (start . ,(if writable | ||
| 5557 | start | ||
| 5558 | (with-current-buffer buffer | ||
| 5559 | (copy-marker start)))))))))) | ||
| 5295 | (tail | 5560 | (tail |
| 5296 | (when (memq type '(vc hc)) | 5561 | (when (memq type '(vc hc)) |
| 5297 | (let (list) | 5562 | (let (list) |
| @@ -5363,7 +5628,8 @@ value can be also stored on disk and read back in a new session." | |||
| 5363 | ((memq type '(vc hc)) | 5628 | ((memq type '(vc hc)) |
| 5364 | (let* ((horizontal (eq type 'hc)) | 5629 | (let* ((horizontal (eq type 'hc)) |
| 5365 | (total (window-size window horizontal pixelwise)) | 5630 | (total (window-size window horizontal pixelwise)) |
| 5366 | (first t) | 5631 | (first t) |
| 5632 | (window-combination-limit (cdr (assq 'combination-limit state))) | ||
| 5367 | size new) | 5633 | size new) |
| 5368 | (dolist (item state) | 5634 | (dolist (item state) |
| 5369 | ;; Find the next child window. WINDOW always points to the | 5635 | ;; Find the next child window. WINDOW always points to the |
| @@ -5406,12 +5672,10 @@ value can be also stored on disk and read back in a new session." | |||
| 5406 | (frame-char-height (window-frame window)) | 5672 | (frame-char-height (window-frame window)) |
| 5407 | 1))))) | 5673 | 1))))) |
| 5408 | (if (window-sizable-p window (- size) horizontal 'safe pixelwise) | 5674 | (if (window-sizable-p window (- size) horizontal 'safe pixelwise) |
| 5409 | (let* ((window-combination-limit | 5675 | (progn |
| 5410 | (assq 'combination-limit item))) | 5676 | (setq new (split-window-no-error |
| 5411 | ;; We must inherit the combination limit, otherwise | 5677 | window size horizontal pixelwise)) |
| 5412 | ;; we might mess up handling of atomic and side | 5678 | (setq window-combination-limit nil)) |
| 5413 | ;; window. | ||
| 5414 | (setq new (split-window window size horizontal pixelwise))) | ||
| 5415 | ;; Give up if we can't resize window down to safe sizes. | 5679 | ;; Give up if we can't resize window down to safe sizes. |
| 5416 | (error "Cannot resize window %s" window)) | 5680 | (error "Cannot resize window %s" window)) |
| 5417 | 5681 | ||
| @@ -5462,7 +5726,8 @@ value can be also stored on disk and read back in a new session." | |||
| 5462 | (nth 3 scroll-bars) (nth 5 scroll-bars))) | 5726 | (nth 3 scroll-bars) (nth 5 scroll-bars))) |
| 5463 | (set-window-vscroll window (cdr (assq 'vscroll state))) | 5727 | (set-window-vscroll window (cdr (assq 'vscroll state))) |
| 5464 | ;; Adjust vertically. | 5728 | ;; Adjust vertically. |
| 5465 | (if (memq window-size-fixed '(t height)) | 5729 | (if (or (memq window-size-fixed '(t height)) |
| 5730 | (window-preserved-size window)) | ||
| 5466 | ;; A fixed height window, try to restore the | 5731 | ;; A fixed height window, try to restore the |
| 5467 | ;; original size. | 5732 | ;; original size. |
| 5468 | (let ((delta | 5733 | (let ((delta |
| @@ -5484,7 +5749,8 @@ value can be also stored on disk and read back in a new session." | |||
| 5484 | window delta nil ignore nil nil nil pixelwise)) | 5749 | window delta nil ignore nil nil nil pixelwise)) |
| 5485 | (window-resize window delta nil ignore pixelwise)))) | 5750 | (window-resize window delta nil ignore pixelwise)))) |
| 5486 | ;; Adjust horizontally. | 5751 | ;; Adjust horizontally. |
| 5487 | (if (memq window-size-fixed '(t width)) | 5752 | (if (or (memq window-size-fixed '(t width)) |
| 5753 | (window-preserved-size window t)) | ||
| 5488 | ;; A fixed width window, try to restore the original | 5754 | ;; A fixed width window, try to restore the original |
| 5489 | ;; size. | 5755 | ;; size. |
| 5490 | (let ((delta | 5756 | (let ((delta |
| @@ -5494,8 +5760,8 @@ value can be also stored on disk and read back in a new session." | |||
| 5494 | (window-size window t pixelwise))) | 5760 | (window-size window t pixelwise))) |
| 5495 | window-size-fixed) | 5761 | window-size-fixed) |
| 5496 | (when (window--resizable-p | 5762 | (when (window--resizable-p |
| 5497 | window delta nil nil nil nil nil pixelwise) | 5763 | window delta t nil nil nil nil pixelwise) |
| 5498 | (window-resize window delta nil nil pixelwise))) | 5764 | (window-resize window delta t nil pixelwise))) |
| 5499 | ;; Else check whether the window is not wide enough. | 5765 | ;; Else check whether the window is not wide enough. |
| 5500 | (let* ((min-size (window-min-size window t ignore pixelwise)) | 5766 | (let* ((min-size (window-min-size window t ignore pixelwise)) |
| 5501 | (delta (- min-size (window-size window t pixelwise)))) | 5767 | (delta (- min-size (window-size window t pixelwise)))) |
| @@ -5540,16 +5806,14 @@ windows can get as small as `window-safe-min-height' and | |||
| 5540 | ;; When WINDOW is internal, reduce it to a live one to put STATE into, | 5806 | ;; When WINDOW is internal, reduce it to a live one to put STATE into, |
| 5541 | ;; see Bug#16793. | 5807 | ;; see Bug#16793. |
| 5542 | (unless (window-live-p window) | 5808 | (unless (window-live-p window) |
| 5543 | (let ((root (frame-root-window window))) | 5809 | (let ((root window)) |
| 5544 | (if (eq window root) | 5810 | (setq window (catch 'live |
| 5545 | (setq window (frame-first-window root)) | 5811 | (walk-window-subtree |
| 5546 | (setq root window) | 5812 | (lambda (window) |
| 5547 | (setq window (catch 'live | 5813 | (when (and (window-live-p window) |
| 5548 | (walk-window-subtree | 5814 | (not (window-parameter window 'window-side))) |
| 5549 | (lambda (window) | 5815 | (throw 'live window))) |
| 5550 | (when (window-live-p window) | 5816 | root))) |
| 5551 | (throw 'live window))) | ||
| 5552 | root)))) | ||
| 5553 | (delete-other-windows-internal window root))) | 5817 | (delete-other-windows-internal window root))) |
| 5554 | 5818 | ||
| 5555 | (set-window-dedicated-p window nil) | 5819 | (set-window-dedicated-p window nil) |
| @@ -5634,6 +5898,75 @@ windows can get as small as `window-safe-min-height' and | |||
| 5634 | (when (eq (window-deletable-p window) t) | 5898 | (when (eq (window-deletable-p window) t) |
| 5635 | (delete-window window)))) | 5899 | (delete-window window)))) |
| 5636 | (window--check frame)))) | 5900 | (window--check frame)))) |
| 5901 | |||
| 5902 | (defun window-swap-states (&optional window-1 window-2 size) | ||
| 5903 | "Swap the states of live windows WINDOW-1 and WINDOW-2. | ||
| 5904 | WINDOW-1 must specify a live window and defaults to the selected | ||
| 5905 | one. WINDOW-2 must specify a live window and defaults to the | ||
| 5906 | window following WINDOW-1 in the cyclic ordering of windows, | ||
| 5907 | excluding minibuffer windows and including live windows on all | ||
| 5908 | visible frames. | ||
| 5909 | |||
| 5910 | Optional argument SIZE non-nil means to try swapping the sizes of | ||
| 5911 | WINDOW-1 and WINDOW-2 as well. A value of `height' means to swap | ||
| 5912 | heights only, a value of `width' means to swap widths only, while | ||
| 5913 | t means to swap both widths and heights, if possible. Frames are | ||
| 5914 | not resized by this function." | ||
| 5915 | (interactive) | ||
| 5916 | (setq window-1 (window-normalize-window window-1 t)) | ||
| 5917 | (if window-2 | ||
| 5918 | (unless (window-live-p window-2) | ||
| 5919 | (error "%s is not a live window" window-2)) | ||
| 5920 | (setq window-2 (next-window window-1 'nomini 'visible))) | ||
| 5921 | (unless (eq window-1 window-2) | ||
| 5922 | (let* ((height (memq size '(t height))) | ||
| 5923 | (width (memq size '(t width))) | ||
| 5924 | (state-1 (window-state-get window-1)) | ||
| 5925 | (width-1 (and width (window-text-width window-1 t))) | ||
| 5926 | (height-1 (and height (window-text-height window-1 t))) | ||
| 5927 | (state-2 (window-state-get window-2)) | ||
| 5928 | (width-2 (and width (window-text-width window-2 t))) | ||
| 5929 | (height-2 (and height (window-text-height window-2 t))) | ||
| 5930 | old preserved) | ||
| 5931 | ;; Swap basic states. | ||
| 5932 | (window-state-put state-1 window-2 t) | ||
| 5933 | (window-state-put state-2 window-1 t) | ||
| 5934 | ;; Swap overlays with `window' property. | ||
| 5935 | (with-current-buffer (window-buffer window-1) | ||
| 5936 | (dolist (overlay (overlays-in (point-min) (point-max))) | ||
| 5937 | (let ((window (overlay-get overlay 'window))) | ||
| 5938 | (cond | ||
| 5939 | ((not window)) | ||
| 5940 | ((eq window window-1) | ||
| 5941 | (overlay-put overlay 'window window-2)) | ||
| 5942 | ((eq window window-2) | ||
| 5943 | (overlay-put overlay 'window window-1)))))) | ||
| 5944 | (unless (eq (window-buffer window-1) (window-buffer window-2)) | ||
| 5945 | (with-current-buffer (window-buffer window-2) | ||
| 5946 | (dolist (overlay (overlays-in (point-min) (point-max))) | ||
| 5947 | (let ((window (overlay-get overlay 'window))) | ||
| 5948 | (cond | ||
| 5949 | ((not window)) | ||
| 5950 | ((eq window window-1) | ||
| 5951 | (overlay-put overlay 'window window-2)) | ||
| 5952 | ((eq window window-2) | ||
| 5953 | (overlay-put overlay 'window window-1))))))) | ||
| 5954 | ;; Try to swap window sizes. | ||
| 5955 | (when size | ||
| 5956 | (unless (= (setq old (window-text-width window-1 t)) width-2) | ||
| 5957 | (window-resize-no-error window-1 (- width-2 old) t t t)) | ||
| 5958 | (unless (= (setq old (window-text-width window-2 t)) width-1) | ||
| 5959 | (setq preserved (window-preserved-size window-1 t)) | ||
| 5960 | (window-preserve-size window-1 t t) | ||
| 5961 | (window-resize-no-error window-2 (- width-1 old) t t t) | ||
| 5962 | (window-preserve-size window-1 t preserved)) | ||
| 5963 | (unless (= (setq old (window-text-height window-1 t)) height-2) | ||
| 5964 | (window-resize-no-error window-1 (- height-2 old) nil t t)) | ||
| 5965 | (unless (= (setq old (window-text-height window-2 t)) height-1) | ||
| 5966 | (setq preserved (window-preserved-size window-1)) | ||
| 5967 | (window-preserve-size window-1 nil t) | ||
| 5968 | (window-resize-no-error window-2 (- height-1 old) nil t t) | ||
| 5969 | (window-preserve-size window-1 nil preserved)))))) | ||
| 5637 | 5970 | ||
| 5638 | (defun display-buffer-record-window (type window buffer) | 5971 | (defun display-buffer-record-window (type window buffer) |
| 5639 | "Record information for window used by `display-buffer'. | 5972 | "Record information for window used by `display-buffer'. |
| @@ -6139,7 +6472,8 @@ hold: | |||
| 6139 | wide as `split-width-threshold'. | 6472 | wide as `split-width-threshold'. |
| 6140 | - When WINDOW is split evenly, the emanating windows are at least | 6473 | - When WINDOW is split evenly, the emanating windows are at least |
| 6141 | `window-min-width' or two (whichever is larger) columns wide." | 6474 | `window-min-width' or two (whichever is larger) columns wide." |
| 6142 | (when (and (window-live-p window) (not (window--side-window-p window))) | 6475 | (when (and (window-live-p window) |
| 6476 | (not (window-parameter window 'window-side))) | ||
| 6143 | (with-current-buffer (window-buffer window) | 6477 | (with-current-buffer (window-buffer window) |
| 6144 | (if horizontal | 6478 | (if horizontal |
| 6145 | ;; A window can be split horizontally when its width is not | 6479 | ;; A window can be split horizontally when its width is not |
| @@ -6314,15 +6648,15 @@ live." | |||
| 6314 | (set-window-dedicated-p window dedicated)) | 6648 | (set-window-dedicated-p window dedicated)) |
| 6315 | (when (memq type '(window frame)) | 6649 | (when (memq type '(window frame)) |
| 6316 | (set-window-prev-buffers window nil))) | 6650 | (set-window-prev-buffers window nil))) |
| 6317 | (let ((parameter (window-parameter window 'quit-restore)) | 6651 | (let ((quit-restore (window-parameter window 'quit-restore)) |
| 6318 | (height (cdr (assq 'window-height alist))) | 6652 | (height (cdr (assq 'window-height alist))) |
| 6319 | (width (cdr (assq 'window-width alist))) | 6653 | (width (cdr (assq 'window-width alist))) |
| 6320 | (size (cdr (assq 'window-size alist))) | 6654 | (size (cdr (assq 'window-size alist))) |
| 6321 | (preserve-size (cdr (assq 'preserve-size alist)))) | 6655 | (preserve-size (cdr (assq 'preserve-size alist)))) |
| 6322 | (cond | 6656 | (cond |
| 6323 | ((or (eq type 'frame) | 6657 | ((or (eq type 'frame) |
| 6324 | (and (eq (car parameter) 'same) | 6658 | (and (eq (car quit-restore) 'same) |
| 6325 | (eq (nth 1 parameter) 'frame))) | 6659 | (eq (nth 1 quit-restore) 'frame))) |
| 6326 | ;; Adjust size of frame if asked for. | 6660 | ;; Adjust size of frame if asked for. |
| 6327 | (cond | 6661 | (cond |
| 6328 | ((not size)) | 6662 | ((not size)) |
| @@ -6340,8 +6674,8 @@ live." | |||
| 6340 | ((functionp size) | 6674 | ((functionp size) |
| 6341 | (ignore-errors (funcall size window))))) | 6675 | (ignore-errors (funcall size window))))) |
| 6342 | ((or (eq type 'window) | 6676 | ((or (eq type 'window) |
| 6343 | (and (eq (car parameter) 'same) | 6677 | (and (eq (car quit-restore) 'same) |
| 6344 | (eq (nth 1 parameter) 'window))) | 6678 | (eq (nth 1 quit-restore) 'window))) |
| 6345 | ;; Adjust height of window if asked for. | 6679 | ;; Adjust height of window if asked for. |
| 6346 | (cond | 6680 | (cond |
| 6347 | ((not height)) | 6681 | ((not height)) |
| @@ -6377,8 +6711,12 @@ live." | |||
| 6377 | ;; Preserve window size if asked for. | 6711 | ;; Preserve window size if asked for. |
| 6378 | (when (consp preserve-size) | 6712 | (when (consp preserve-size) |
| 6379 | (window-preserve-size window t (car preserve-size)) | 6713 | (window-preserve-size window t (car preserve-size)) |
| 6380 | (window-preserve-size window nil (cdr preserve-size)))))) | 6714 | (window-preserve-size window nil (cdr preserve-size))))) |
| 6381 | 6715 | ;; Assign any window parameters specified. | |
| 6716 | (let ((parameters (cdr (assq 'window-parameters alist)))) | ||
| 6717 | (dolist (parameter parameters) | ||
| 6718 | (set-window-parameter | ||
| 6719 | window (car parameter) (cdr parameter))))) | ||
| 6382 | window)) | 6720 | window)) |
| 6383 | 6721 | ||
| 6384 | (defun window--maybe-raise-frame (frame) | 6722 | (defun window--maybe-raise-frame (frame) |
| @@ -6602,6 +6940,9 @@ Recognized alist entries include: | |||
| 6602 | preserve the width of the window, (nil . t) to preserve its | 6940 | preserve the width of the window, (nil . t) to preserve its |
| 6603 | height or (t . t) to preserve both. | 6941 | height or (t . t) to preserve both. |
| 6604 | 6942 | ||
| 6943 | `window-parameters' -- Value specifies an alist of window | ||
| 6944 | parameters to give the chosen window. | ||
| 6945 | |||
| 6605 | The ACTION argument to `display-buffer' can also have a non-nil | 6946 | The ACTION argument to `display-buffer' can also have a non-nil |
| 6606 | and non-list value. This means to display the buffer in a window | 6947 | and non-list value. This means to display the buffer in a window |
| 6607 | other than the selected one, even if it is already displayed in | 6948 | other than the selected one, even if it is already displayed in |
| @@ -6952,10 +7293,7 @@ selected frame." | |||
| 6952 | (window--display-buffer | 7293 | (window--display-buffer |
| 6953 | buffer window 'window alist display-buffer-mark-dedicated)) | 7294 | buffer window 'window alist display-buffer-mark-dedicated)) |
| 6954 | (and (not (frame-parameter nil 'unsplittable)) | 7295 | (and (not (frame-parameter nil 'unsplittable)) |
| 6955 | (setq window | 7296 | (setq window (split-window-no-error (window-main-window))) |
| 6956 | (condition-case nil | ||
| 6957 | (split-window (window--major-non-side-window)) | ||
| 6958 | (error nil))) | ||
| 6959 | (window--display-buffer | 7297 | (window--display-buffer |
| 6960 | buffer window 'window alist display-buffer-mark-dedicated)) | 7298 | buffer window 'window alist display-buffer-mark-dedicated)) |
| 6961 | (and (setq window bottom-window) | 7299 | (and (setq window bottom-window) |