子框架是介于普通窗口 (see Windows) 与“ “标准(normal)” 框架之间的对象。与窗口类似,它们依附于一个所属框架;与窗口不同的是,它们可以互相重叠—修改一个子框架的大小或位置不会改变其兄弟子框架的大小或位置。
按照设计,创建或修改子框架的操作均借助框架参数实现 (see 框架参数),不使用任何专用函数或可自定义变量。请注意,子框架仅在图形终端上有效。
要创建新的子框架,或将一个标准框架转换为子框架,只需将该框架的 parent-frame 参数 (see 框架交互参数) 设置为一个已存在的框架。只要该参数不被修改或重置,由此参数指定的框架即为该框架的父框架。从技术上讲,这会使子框架对应的窗口系统窗口成为父框架窗口系统窗口的子窗口。
parent-frame 参数可以随时修改。
将其设置为另一个框架会 重设父级(reparents) 该子框架。
将其设置为另一个子框架会使该框架成为 嵌套(nested) 子框架。
将其设置为 nil 会恢复该框架为顶层框架—即其窗口系统窗口为显示根窗口的子窗口。23
由于子框架可以任意嵌套,一个框架可以同时是子框架和父框架。此外,子框架与父框架的相对角色可以随时反转(尽管通常建议子框架尺寸明显小于父框架)。尝试将一个框架设为自身的祖先框架会触发错误。
大多数窗口系统会在父框架的原生边界处裁剪子框架 (see 框架几何属性)—超出这些边界的内容通常不可见。子框架的 left 和 top 参数指定相对于其父框架原生区域左上角的位置。当父框架大小改变时,该位置在逻辑上保持不变。
NS 版本不会在父框架边界处裁剪子框架,允许将子框架放置在不遮挡父框架的位置同时自身保持可见。
通常,移动父框架会同时移动其所有子框架及后代框架,并保持它们的相对位置不变。请注意,仅当子框架相对于其父框架的位置发生改变时,才会为该子框架运行钩子 move-frame-functions (see 框架位置)。
当父框架大小改变时,其子框架在逻辑上保留原有尺寸以及相对于父框架左上角的位置。这意味着当父框架缩小时,子框架可能会(部分)不可见。参数 keep-ratio (see 框架交互参数) 可用于在父框架缩放时按比例调整子框架的大小与位置,避免父框架缩小时子框架被遮挡。
可见的子框架始终显示在其父框架之上并遮挡其部分内容,NS 版本除外,子框架可被置于父框架之下。这与顶层框架的窗口系统窗口类似,它也始终显示在其父窗口—桌面根窗口之上。当父框架被图标化或设为不可见时 (see 框架的可见性),其子框架会被设为不可见;当父框架取消图标化或设为可见时,其子框架会被设为可见。
当父框架即将被删除时 (see 删除框架),其子框架会在父框架删除前被递归删除。该规则有一个例外:当子框架作为另一个框架的代理迷你缓冲区框架时 (see 迷你缓冲区与框架),它会被保留至父框架删除完成。如果此时没有剩余框架使用该子框架作为迷你缓冲区框架,Emacs 会尝试删除该子框架。若删除因任何原因失败,则该子框架会被转为顶层框架。
子框架能否显示菜单栏或工具栏取决于窗口系统或窗口管理器。大多数窗口系统明确禁止子框架使用菜单栏。建议通过框架初始参数设置同时禁用菜单栏与工具栏。
通常,子框架不显示窗口管理器装饰,如标题栏或外边框 (see 框架几何属性)。当子框架不显示菜单栏或工具栏时,可以使用框架的其他边框 (see 布局参数) 替代外边框。
具体而言,在 X 环境下(非 GTK+ 编译版本)可使用框架外边框;在 MS-Windows 上,指定非零外边框宽度会显示一个 1 像素宽的外边框。在所有窗口系统下均可使用内边框。无论哪种情况,建议通过 undecorated 框架参数 (see 窗口管理参数) 禁用子框架的窗口管理器装饰。
要使用鼠标调整无装饰子框架的大小或位置,需要使用专用框架参数 (see 鼠标拖动参数)。如果子框架存在内边框,且其 drag-internal-border 参数为非 nil,则可通过内边框使用鼠标调整框架大小。如果设置了 snap-width 参数,该数值表示框架在其父框架对应边缘或角落处 吸附对齐(snaps) 的像素距离。
有两种方式可使用鼠标拖动整个子框架:如果 drag-with-mode-line 参数为非 nil,可通过最底部窗口的模式行区域拖动无迷你缓冲区窗口的框架 (see Minibuffer 窗口);如果 drag-with-header-line 参数为非 nil,可通过最顶部窗口的标题行区域拖动框架。
为给子框架设置可拖动的标题行或模式行,窗口参数 mode-line-format 和 header-line-format 十分方便 (see 窗口参数)。它们可以移除不需要的模式行(选择使用 drag-with-header-line 时),并消除可能干扰框架拖动的鼠标敏感区域。
当用户使用鼠标拖动框架并超出范围时,很容易将框架拖出父框架的屏幕区域,松开鼠标后找回此类框架会十分麻烦。为避免这种情况,建议设置框架的 top-visible 或 bottom-visible 参数 (see 鼠标拖动参数)。
如果你希望允许用户通过标题行拖动子框架,可将其子框架的 top-visible 参数设为一个数值。将 top-visible 设为数值会禁止将子框架的上边缘拖至其父框架上边缘之上。如果你希望通过模式行拖动框架,可将 bottom-visible 参数设为一个数值;这会禁止将子框架的下边缘拖至其父框架下边缘之下。无论哪种情况,该数值同时指定拖动期间子框架保持可见区域的宽度与高度(以像素为单位)。
当子框架通过 display-buffer-in-child-frame 用于显示缓冲区时 (see 缓冲区显示动作函数),可将框架的 auto-hide-function 参数 (see 框架交互参数) 设置为一个函数,以便在退出显示该缓冲区的窗口时合理处理该框架。
当子框架用于迷你缓冲区交互(例如在独立窗口中显示补全项)时,minibuffer-exit 参数 (see 框架交互参数) 可用于在退出迷你缓冲区时处理该框架。
子框架的行为在许多其他方面也与顶层框架不同。以下简述部分差异:
iconify-frame 会尝试图标化该子框架对应的顶层框架。如需修改此行为,用户可自定义下文描述的选项 iconify-child-frame。
z-group (see 位置参数) 仅会改变拥有同一父框架的子框架之间的堆叠顺序。
mouse-autoselect-window 可改善此问题 (see 鼠标窗口自动选择)。
以下两个函数在处理子框架与父框架时十分有用:
此函数返回 frame 的父框架。frame 的父框架是指其窗口系统窗口为 frame 对应窗口系统窗口父窗口的 Emacs 框架。如果存在这样的框架,则 frame 被视为该框架的子框架。
如果 frame 没有父框架,此函数返回 nil。
如果 ancestor 是 descendant 的祖先框架,此函数返回非 nil。ancestor 是 descendant 的祖先框架,当且仅当其是 descendant 的父框架,或是 descendant 父框架的祖先框架。ancestor 与 descendant 都必须指定存活的框架。
另请注意函数 window-largest-empty-rectangle (see 坐标与窗口),它可用于在现有窗口的最大空白区域内嵌子框架,有助于避免子框架遮挡窗口中显示的文本。
自定义以下选项可用于调整子框架上 iconify-frame 的行为。
该选项告知 Emacs 在收到图标化子框架请求时如何处理。如果为 nil,对子框架调用 iconify-frame 不会执行任何操作。如果为 iconify-top-level,Emacs 会尝试图标化该子框架的顶层祖先框架。如果为 make-invisible,Emacs 会尝试将该子框架设为不可见而非图标化。
其他值则表示尝试直接图标化子框架。由于并非所有窗口管理器都会响应此操作,甚至可能导致子框架无法响应用户操作,因此默认行为是图标化对应的顶层框架。