30.3.1 框架布局

可见框架在其终端显示器上占据一块矩形区域。 该区域可包含多个嵌套矩形,各自承担不同用途。 下图示意了图形终端上框架的布局:


        <------------ Outer Frame Width ----------->
        ____________________________________________
     ^(0)  ________ External/Outer Border _______   |
     | |  |_____________ Title Bar ______________|  |
     | | (1)_____________ Menu Bar ______________|  | ^
     | | (2)_____________ Tool Bar ______________|  | ^
     | | (3)_____________ Tab Bar _______________|  | ^
     | |  |  _________ Internal Border ________  |  | ^
     | |  | |   ^                              | |  | |
     | |  | |   |                              | |  | |
Outer  |  | | Inner                            | |  | Native
Frame  |  | | Frame                            | |  | Frame
Height |  | | Height                           | |  | Height
     | |  | |   |                              | |  | |
     | |  | |<--+--- Inner Frame Width ------->| |  | |
     | |  | |   |                              | |  | |
     | |  | |___v______________________________| |  | |
     | |  |___________ Internal Border __________|  | |
     | | (4)__________ Bottom Tool Bar __________|  | v
     v |___________ External/Outer Border __________|
           <-------- Native Frame Width -------->

实际使用中,图中所示区域并非全部都会出现。 这些区域的含义如下所述。

外部框架

outer frame 外部框架 是包含图中所有区域的矩形。 该矩形的边缘称为框架的 outer edges 外边缘。 框架的 outer width 外部宽度outer height 外部高度 共同决定了该矩形的 outer size 外部尺寸

了解框架外部尺寸有助于将框架适配到显示器的工作区域 (see 多终端)或在屏幕上并排摆放两个框架。 通常,框架的外部尺寸只有在框架至少被映射一次(设为可见, see 框架的可见性)之后才能获取。 对于初始框架或尚未创建的框架,外部尺寸只能估算, 或必须根据窗口系统或窗口管理器的默认值计算。 一种变通方法是获取已映射框架的外部尺寸与原生尺寸(见下文)之差, 并用其计算新框架的外部尺寸。

外部框架左上角的位置(上图中标记为 ‘(0)’) 即为框架的 outer position 外部位置。 图形框架的外部位置也常被称作框架的“位置”, 因为无论框架如何调整大小或改变布局,它在显示器上通常保持不变。

外部位置由框架参数 lefttop 指定并可通过其设置 (see 位置参数)。 对于普通顶层框架,这些参数通常表示其相对于显示器原点的绝对位置(见下文)。 对于子框架(see 子框架),这些参数表示其相对于父框架 原生位置(见下文)的相对位置。 对于文本终端上的框架,这些参数的值无意义且始终为零。

外部边框

external border 外部边框 是窗口管理器提供的装饰部分。 它通常用于鼠标调整框架大小,因此在“全屏”和最大化框架上不会显示 (see 尺寸参数)。其宽度由窗口管理器决定, 无法通过 Emacs 函数修改。

文本终端框架不存在外部边框。 对于图形框架,可通过设置 override-redirectundecorated 框架参数禁止显示外部边框 (see 窗口管理参数)。

外边框

outer border 外边框 是独立边框,其宽度可通过 border-width 框架参数指定(see 布局参数)。 实际中,框架的外部边框或外边框只会显示其中一种,不会同时出现。 通常,外边框仅在不受窗口管理器(完全)控制的特殊框架上显示, 例如工具提示框架(see 工具提示)、子框架(see 子框架) 以及 undecoratedoverride-redirect 框架 (see 窗口管理参数)。

外边框在文本终端框架与 GTK+ 生成的框架上从不显示。 在 MS-Windows 上,外边框通过 1 像素宽的外部边框模拟。 X 环境下非工具包构建版本可通过设置 border-color 框架参数 修改外边框颜色(see 布局参数)。

标题栏

title bar 标题栏,又称 caption bar caption 栏, 同样是窗口管理器装饰的一部分,通常显示框架标题 (see 框架标题)以及最小化、最大化、关闭框架按钮。 它也可用于鼠标拖动框架。 标题栏通常不会在全屏(see 尺寸参数)、 工具提示(see 工具提示)和子框架(see 子框架)上显示, 终端框架则不存在标题栏。 可通过设置 override-redirectundecorated 框架参数 禁止显示标题栏(see 窗口管理参数)。

菜单栏

菜单栏(see 菜单栏)可以是内部(由 Emacs 自身绘制) 或外部(由工具包绘制)。 大多数构建版本(GTK+、Lucid、Motif、MS-Windows)使用外部菜单栏。 NS 也使用外部菜单栏,但它不属于外部框架。 非工具包构建版本可提供内部菜单栏。 在文本终端框架上,菜单栏是框架根窗口的一部分 (see 窗口与框架)。 通常,子框架(see 子框架)从不显示菜单栏。 可通过将 menu-bar-lines 参数(see 布局参数)设为零 禁止显示菜单栏。

当菜单栏宽度过大无法在框架内完整显示时,是换行还是截断 取决于所用工具包。通常只有 Motif 和 MS-Windows 版本可以换行菜单栏。 当它们切换菜单栏换行状态时,会尽量保持框架外部高度不变, 因此框架的原生高度(见下文)会相应改变。

工具栏

与菜单栏类似,工具栏(see 工具栏) 可以是内部(由 Emacs 自身绘制)或外部(由工具包绘制)。 GTK+ 与 NS 版本的工具栏由工具包绘制,其余版本使用内部工具栏。 在 GTK+ 中,工具栏可位于框架任意一侧,紧邻内边框外侧,见下文。 子框架(see 子框架)通常不显示工具栏。 可通过将 tool-bar-lines 参数(see 布局参数)设为零 禁止显示工具栏。

如果变量 auto-resize-tool-barsnil, 当内部工具栏宽度超出框架时,Emacs 会对其换行。 当 Emacs 切换内部工具栏换行状态时,默认保持框架外部高度不变, 因此框架的原生高度(见下文)会相应改变。 而使用 GTK+ 构建的 Emacs 从不会换行工具栏, 但可能自动增加框架外部宽度以容纳过长的工具栏。

标签栏

标签栏(see Tab Bars in The GNU Emacs Manual) 始终由 Emacs 自身绘制。 在使用内部工具栏的 Emacs 版本中,标签栏出现在工具栏上方; 在使用外部工具栏的版本中,标签栏出现在工具栏下方。 可通过将 tab-bar-lines 参数(see 布局参数)设为零 禁止显示标签栏。

原生框架

native frame 原生框架 是完全位于外部框架内部的矩形。 它排除了外部边框、外边框、标题栏以及任何外部菜单/工具栏所占区域。 原生框架的边缘称为框架的 native edges 原生边缘。 框架的 native width 原生宽度native height 原生高度 共同决定了框架的 native size 原生尺寸

框架的原生尺寸是 Emacs 在内部创建或调整框架时, 传递给窗口系统或窗口管理器的尺寸。 当窗口系统或窗口管理器调整框架的窗口系统窗口时, 例如点击标题栏最大化框架或用鼠标拖动外部边框时, Emacs 也会从其获取该尺寸。

原生框架左上角的位置即为框架的 native position 原生位置。 上图中 (1)––(3) 标记了不同构建版本的该位置:

  • (1) 非工具包、Android、Haiku 及终端框架
  • (2) Lucid、Motif 及 MS-Windows 框架
  • (3) GTK+ 及 NS 框架

相应地,框架的原生高度可能包含工具栏高度但不包含菜单栏高度 (Lucid、Motif、MS-Windows), 或同时不包含菜单栏与工具栏高度(非工具包与文本终端框架)。

如果原生位置本应为 (2),但工具栏如图 (4) 所示位于框架底部, 则框架的原生位置变为标签栏位置。

框架的原生位置是设置或返回鼠标当前位置的函数 (see 鼠标位置)以及处理窗口位置的函数 (如 window-edgeswindow-atcoordinates-in-window-p, see 坐标与窗口)的参考位置。 它同时也是在该框架内定位子框架的 (0, 0) 原点 (see 子框架)。

另请注意,通过修改框架的 override-redirectundecorated 参数添加或移除窗口管理器装饰时 (see 窗口管理参数), 框架的原生位置在显示器上通常保持不变。

内边框

内边框是 Emacs 围绕内部框架(见下文)绘制的边框。 其外观设置取决于该框架是否为子框架(see 子框架)。

对于普通框架,其宽度由 internal-border-width 框架参数指定 (see 布局参数),颜色由 internal-border 面孔的背景色指定。

对于子框架,其宽度由 child-frame-border-width 框架参数指定 (未指定时回退使用 internal-border-width 参数), 颜色由 child-frame-border 面孔的背景色指定。

内部框架

inner frame 内部框架 是为框架窗口预留的矩形区域。 它由内边框包围,但内边框不属于内部框架。 其边缘称为框架的 inner edges 内边缘inner width 内部宽度inner height 内部高度 决定了该矩形的 inner size 内部尺寸。 内部框架有时也被称作框架的 display area 显示区域

通常,内部框架被划分为框架的根窗口(see 窗口与框架) 与框架的迷你缓冲区窗口(see Minibuffer 窗口)。 该规则有两个明显例外: minibuffer-less frame 无迷你缓冲区框架 仅包含根窗口,不含迷你缓冲区窗口; minibuffer-only frame 仅迷你缓冲区框架 仅包含迷你缓冲区窗口, 该窗口同时充当框架的根窗口。 创建此类框架配置的方式见 初始框架参数

文本区域

框架的 text area 文本区域 是一个可嵌入原生框架的虚拟区域。 其位置未指定。宽度可由原生宽度减去内边框、一个垂直滚动条 以及左右 fringe(若已为框架指定)的宽度得到, 见 布局参数。 高度可由原生高度减去内边框宽度、框架内部菜单/工具栏高度、 标签栏高度以及一个水平滚动条(若已指定)的高度得到。

框架的 absolute position 绝对位置 以 (X, Y) 坐标对给出, 表示相对于框架显示器原点 (0, 0) 的水平与垂直像素偏移。 相应地,框架的 absolute edges 绝对边缘 以相对于该原点的像素偏移表示。

注意,在多显示器环境下,显示器原点不一定与终端整个可用显示区域的左上角重合。 因此在此类环境中,即使框架完全可见,其绝对位置也可能为负值。

按照惯例,垂直偏移“向下”递增。 这意味着框架高度等于下边缘偏移减去上边缘偏移。 水平偏移如预期般“向右”递增, 因此框架宽度等于右边缘偏移减去左边缘偏移。

对于图形终端上的框架,以下函数返回上述区域的尺寸:

Function: frame-geometry &optional frame

该函数返回 frame 的几何属性。 返回值为包含下列属性的关联列表。 所有坐标、高度与宽度值均为以像素计数的整数。 注意,如果 frame 尚未被映射(see 框架的可见性), 部分返回值可能仅为实际值的近似值——即框架映射后可见的真实值。

outer-position

一个 cons 对,表示外部 frame 相对于其显示器原点 (0, 0) 的绝对位置。

outer-size

一个 cons 对,表示 frame 的外部宽度与高度。

external-border-size

一个 cons 对,表示窗口管理器提供的 frame 外部边框的水平与垂直宽度。 如果窗口管理器未提供这些值,Emacs 会尝试从外部框架与内部框架的坐标中推算。

outer-border-width

frame 外边框的宽度。该值仅对非 GTK+ 的 X 构建版本有意义。

title-bar-size

一个 cons 对,表示窗口管理器或操作系统提供的 frame 标题栏宽度与高度。 若两者均为零,则框架无标题栏。若仅宽度为零,表示 Emacs 无法获取宽度信息。

menu-bar-external

若非 nil,表示菜单栏为外部(不属于 frame 的原生框架)。

menu-bar-size

一个 cons 对,表示 frame 菜单栏的宽度与高度。

tool-bar-external

若非 nil,表示工具栏为外部(不属于 frame 的原生框架)。

tool-bar-position

表示 frame 上工具栏的位置,可为 lefttoprightbottom 之一。

leftright 仅在使用 GTK+ 工具包的构建版本上支持; bottom 除 NS 外所有版本均支持; top 在所有环境均支持。

tool-bar-size

一个 cons 对,表示 frame 工具栏的宽度与高度。

internal-border-width

frame 内边框的宽度。

以下函数可用于获取外部、原生与内部框架的边缘。

Function: frame-edges &optional frame type

该函数返回 frame 的外部、原生或内部框架的绝对边缘。 frame 必须为可用框架,默认为当前选中框架。 返回列表格式为 (left top right bottom), 所有值均为相对于 frame 显示器原点的像素值。 对于终端框架,返回的 lefttop 始终为零。

可选参数 type 指定要返回的边缘类型: outer-edges 表示返回 frame 的外边缘, native-edges(或 nil)表示返回原生边缘, inner-edges 表示返回内边缘。

按照惯例,lefttop 对应位置的显示器像素 被视为属于 frame。 因此若 lefttop 均为零, 显示器原点处的像素属于 frame。 而 bottomright 处的像素 被视为紧邻 frame 外侧。 这意味着,例如两个并排框架的左侧框架右外边缘 与右侧框架左外边缘重合时,该边缘像素属于右侧框架。