当删除窗口 W 的最后一个同级窗口时,其父窗口也会被删除,W 会在窗口树中替代它。这意味着 W 必须与其父窗口的同级窗口重组,以形成新的窗口组合(see 窗口与框架)。在某些情况下,删除一个活动窗口甚至可能导致两个内部窗口被删除。
______________________________________
| ______ ____________________________ |
|| || __________________________ ||
|| ||| ___________ ___________ |||
|| |||| || ||||
|| ||||____W6_____||_____W7____||||
|| |||____________W4____________|||
|| || __________________________ ||
|| ||| |||
|| ||| |||
|| |||____________W5____________|||
||__W2__||_____________W3_____________ |
|__________________W1__________________|
在该布局中删除 W5 通常会导致 W3 和 W4 被删除。剩余的活动窗口 W2、W6 和 W7 会被重组,形成一个以 W1 为父窗口的新水平组合。
不过,有时不删除像 W4 这样的父窗口是合理的。特别是当父窗口被用于保留嵌入在同类型组合中的组合时,不应移除该父窗口。这种嵌入方式可以确保,当你拆分一个窗口并随后删除新窗口时,Emacs 会恢复对应框架在拆分前的布局。
考虑一个初始场景:有两个活动窗口 W2 和 W3,以及它们的父窗口 W1。
______________________________________
| ____________________________________ |
|| ||
|| ||
|| ||
|| ||
|| ||
|| ||
||_________________W2_________________||
| ____________________________________ |
|| ||
|| ||
||_________________W3_________________||
|__________________W1__________________|
如下拆分 W2 以创建新窗口 W4。
______________________________________
| ____________________________________ |
|| ||
|| ||
||_________________W2_________________||
| ____________________________________ |
|| ||
|| ||
||_________________W4_________________||
| ____________________________________ |
|| ||
|| ||
||_________________W3_________________||
|__________________W1__________________|
现在,当垂直放大窗口时,Emacs 会尝试从其下方的同级窗口获取相应空间(如果该窗口存在)。在本场景中,放大 W4 会从 W3 占用空间。
______________________________________
| ____________________________________ |
|| ||
|| ||
||_________________W2_________________||
| ____________________________________ |
|| ||
|| ||
|| ||
|| ||
||_________________W4_________________||
| ____________________________________ |
||_________________W3_________________||
|__________________W1__________________|
删除 W4 会将其全部空间归还给 W2,包括之前从 W3 占用的空间。
______________________________________
| ____________________________________ |
|| ||
|| ||
|| ||
|| ||
|| ||
|| ||
|| ||
|| ||
||_________________W2_________________||
| ____________________________________ |
||_________________W3_________________||
|__________________W1__________________|
这可能不符合直觉,特别是当 W4 仅被临时用于显示缓冲区时(see 临时显示),而你希望继续使用初始布局。
通过在拆分 W2 时创建新的父窗口,可以修复该行为。下面描述的变量支持这一设置。
该变量控制拆分窗口时是否创建新的父窗口。支持以下值:
nil表示如果存在现有父窗口,且拆分方向与现有窗口组合方向一致,则新活动窗口可以共享该父窗口(否则仍会创建新的内部窗口)。
window-size表示当 display-buffer 拆分窗口并在 alist 参数中传入 window-height 或 window-width 条目时,会创建新的父窗口(see 缓冲区显示动作函数)。其他情况下,窗口拆分行为与值为 nil 时一致。
temp-buffer-resize表示当 with-temp-buffer-window 拆分窗口且启用了 temp-buffer-resize-mode 时,会创建新的父窗口(see 临时显示)。其他情况下,行为与 nil 一致。
temp-buffer表示 with-temp-buffer-window 在拆分现有窗口时始终创建新的父窗口(see 临时显示)。其他情况下,行为与 nil 一致。
display-buffer表示当 display-buffer(see 为显示缓冲区选择窗口)拆分窗口时,始终创建新的父窗口。其他情况下,行为与 nil 一致。
t表示拆分窗口时始终创建新的父窗口。因此,如果该变量的值始终为 t,则任何窗口树都是二叉树(即除根窗口外,每个窗口都恰好有一个同级窗口)。
默认值为 window-size。其他值保留供将来使用。
如果由于该变量的设置,split-window 创建了新的父窗口,它还会对新创建的内部窗口调用 set-window-combination-limit(见下文)。这会影响删除子窗口时窗口树的重排方式(见下文)。
如果 window-combination-limit 为 t,在本场景的初始布局中拆分 W2 会产生如下结果:
______________________________________
| ____________________________________ |
|| __________________________________ ||
||| |||
|||________________W2________________|||
|| __________________________________ ||
||| |||
|||________________W4________________|||
||_________________W5_________________||
| ____________________________________ |
|| ||
|| ||
||_________________W3_________________||
|__________________W1__________________|
创建了一个新的内部窗口 W5;其子窗口为 W2 和新的活动窗口 W4。现在 W2 是 W4 的唯一同级窗口,因此放大 W4 会尝试缩小 W2,而 W3 不受影响。可以看到,W5 表示嵌入在垂直组合 W1 中的两个窗口的垂直组合。
该函数将窗口 window 的 组合限制 设置为 limit。该值可通过函数 window-combination-limit 获取。其效果见下文;注意该值仅对内部窗口有意义。当调用 split-window 时,如果变量 window-combination-limit 为 t,它会自动调用该函数,并将 t 作为 limit 传入。
该函数返回 window 的组合限制。
组合限制仅对内部窗口有意义。如果为 nil,则 Emacs 可以在删除窗口时自动删除 window,以便将 window 的子窗口与其同级窗口分组,形成新的窗口组合。如果组合限制为 t,则 window 的子窗口永远不会与其同级窗口自动重组。
在本节开头所示的布局中,如果 W4(W6 和 W7 的父窗口)的组合限制为 t,则删除 W5 不会同时隐式删除 W4。
另外,每当同一组合中的某个窗口被拆分或删除时,通过始终调整该组合中所有窗口的大小,可以避免上述问题。这也允许拆分原本过小而无法执行该操作的窗口。
如果该变量为 nil,则 split-window 仅能在窗口(记为 window)的屏幕区域足够容纳自身和新窗口时拆分它。
如果该变量为 t,则 split-window 会尝试调整与 window 属于同一组合的所有窗口的大小,以容纳新窗口。特别地,即使 window 是固定尺寸窗口或通常过小无法拆分,该设置也可能使 split-window 成功执行。此外,后续调整或删除 window 可能会调整其组合中所有其他窗口的大小。
默认值为 nil。其他值保留供将来使用。如果某个拆分操作受非 nil 的 window-combination-limit 值影响,则可能忽略该变量的值。
为说明 window-combination-resize 的效果,考虑以下框架布局。
______________________________________
| ____________________________________ |
|| ||
|| ||
|| ||
|| ||
||_________________W2_________________||
| ____________________________________ |
|| ||
|| ||
|| ||
|| ||
||_________________W3_________________||
|__________________W1__________________|
如果 window-combination-resize 为 nil,拆分窗口 W3 不会改变 W2 的大小:
______________________________________
| ____________________________________ |
|| ||
|| ||
|| ||
|| ||
||_________________W2_________________||
| ____________________________________ |
|| ||
||_________________W3_________________||
| ____________________________________ |
|| ||
||_________________W4_________________||
|__________________W1__________________|
如果 window-combination-resize 为 t,拆分 W3 会使三个活动窗口的高度大致相等:
______________________________________
| ____________________________________ |
|| ||
|| ||
||_________________W2_________________||
| ____________________________________ |
|| ||
|| ||
||_________________W3_________________||
| ____________________________________ |
|| ||
|| ||
||_________________W4_________________||
|__________________W1__________________|
删除活动窗口 W2、W3 或 W4 中的任意一个,都会将其空间按比例分配给剩余的两个活动窗口。