本节介绍 Lisp 程序如何在窗口发生滚动或其他窗口变更后执行相应操作。首先讨论窗口显示缓冲区不同区域的情形。
该变量保存一组函数,Emacs 在重显示发生滚动的窗口之前会调用这些函数。在窗口中显示其他缓冲区、创建新窗口时也会调用这些函数。
该变量并非普通钩子,因为每个函数被调用时会传入两个参数:窗口对象,及其新的显示起始位置。调用时,参数窗口的显示起始位置已被设置为新值,且窗口中将要显示的缓冲区已设为当前缓冲区。
这些函数在使用 window-end 时需要格外注意(see 窗口起始与结束位置);如需获取最新值,必须使用其 update 参数以确保更新。
警告:不要使用此功能改变窗口的滚动方式。该机制并非为此设计,这样做通常无法正常工作。
此外,你可以使用 jit-lock-register 注册字体锁定(Font Lock)的高亮函数,当窗口滚动或尺寸改变导致缓冲区部分内容被(重新)高亮时,该函数会被调用。See 字体锁定其他变量。
本节剩余部分介绍六个钩子,当重显示过程中检测到窗口发生显著的非滚动类变更时会运行这些钩子。为简便起见,这些钩子及其调用的函数统称为 窗口变更函数(window change functions)。与所有钩子一样,这些钩子既可以全局设置,也可以在安装时通过 add-hook 的 local 参数设置为缓冲区局部生效(see 设置钩子)。
第一个钩子在检测到 窗口缓冲区变更(window buffer change) 后运行,即窗口被创建、删除或分配了其他缓冲区时。
该变量指定在重显示期间、窗口缓冲区发生变更时调用的函数。其值应为一组接收单个参数的函数。
缓冲区局部指定的函数,会对所有显示该缓冲区的窗口执行调用——只要该窗口自上一轮窗口变更函数运行后被创建或分配了该缓冲区。此时窗口对象会作为参数传入。
默认值指定的函数,会对某个 框架 执行调用——只要该 框架 上至少有一个窗口自上一轮后被添加、删除或分配了其他缓冲区。此时 框架 对象会作为参数传入。
第二个钩子在检测到 窗口尺寸变更(window size change) 时运行,即窗口被创建、分配其他缓冲区,或总尺寸、文本区域尺寸发生改变时。
该变量指定在重显示期间、窗口尺寸发生变更时调用的函数。其值应为一组接收单个参数的函数。
缓冲区局部指定的函数,会对所有显示该缓冲区的窗口执行调用——只要该窗口自上一轮后被添加、分配其他缓冲区,或总尺寸/主体尺寸发生改变。此时窗口对象会作为参数传入。
默认值指定的函数,会对某个 框架 执行调用——只要该 框架 上至少有一个窗口自上一轮后被添加、分配其他缓冲区,或总尺寸/主体尺寸发生改变。此时 框架 对象会作为参数传入。
第三个钩子在检测到 窗口选中变更(window selection change) 时运行,即自上一次重显示后选中了其他窗口。
该变量指定在重显示期间、选中窗口或 框架 的选中窗口发生改变时调用的函数。其值应为一组接收单个参数的函数。
缓冲区局部指定的函数,会对所有显示该缓冲区的窗口执行调用——只要该窗口自上一轮后被选中或取消选中(在全部窗口或所在 框架 的窗口范围内)。此时窗口对象会作为参数传入。
默认值指定的函数,会对某个 框架 执行调用——只要该 框架 被选中/取消选中,或其选中窗口发生改变。此时 框架 对象会作为参数传入。
第四个钩子在检测到 窗口状态变更(window state change) 时运行,即前述三种窗口变更中至少一种发生时。
该变量指定在重显示期间、窗口缓冲区/尺寸变更,或选中窗口/ 框架 选中窗口改变时调用的函数。其值应为一组接收单个参数的函数。
缓冲区局部指定的函数,会对所有显示该缓冲区的窗口执行调用——只要该窗口自上一轮后被添加、分配其他缓冲区、尺寸改变,或被选中/取消选中。此时窗口对象会作为参数传入。
默认值指定的函数,会对某个 框架 执行调用——只要该 框架 上至少有一个窗口被添加、删除、分配其他缓冲区、尺寸改变,或 框架 本身被选中/取消选中、选中窗口改变。此时 框架 对象会作为参数传入。
默认值指定的函数还会在某个 框架 的窗口状态变更标记(见下文)自上一次重显示以来被设置时运行。
第五个钩子在检测到 窗口配置变更(window configuration change) 时运行,即窗口的缓冲区或尺寸发生改变。其运行方式与前四个钩子不同。
该变量指定在重显示期间、窗口缓冲区或尺寸发生改变时调用的函数。其值应为一组无参数函数。
缓冲区局部指定的函数,会对所有显示该缓冲区的窗口执行调用——只要其所在 框架 上至少有一个窗口自上一轮后被添加、删除、分配其他缓冲区或尺寸改变。每次调用都会临时选中显示该缓冲区的窗口,并将其缓冲区设为当前缓冲区。
默认值指定的函数,会对每个满足条件的 框架 执行调用——只要该 框架 上至少有一个窗口自上一轮后被添加、删除、分配其他缓冲区或尺寸改变。每次调用都会临时选中该 框架,并将其选中窗口的缓冲区设为当前缓冲区。
最后,Emacs 会运行一个通用化 window-state-change-functions 行为的普通钩子。
该变量的默认值指定在重显示期间、检测到窗口状态变更,或至少一个 框架 的窗口状态变更标记被设置时调用的函数。其值应为一组无参数函数。
应用程序仅在需要响应自上一次重显示以来两个或更多 框架 上发生(或被标记)的变更时,才应将函数加入此钩子。其他情况下优先使用 window-state-change-functions。
窗口变更函数在每个 框架 的重显示期间按如下顺序调用:首先按顺序运行所有缓冲区局部的窗口缓冲区变更、尺寸变更、选中窗口变更及窗口状态变更函数;随后以相同顺序运行这些函数的默认值版本;接着运行缓冲区局部的窗口配置变更函数,再运行其默认值函数;最后运行 window-state-change-hook 中的函数。
窗口变更函数仅在对应 框架 此前已登记相关变更时才会为其运行。这类变更包括创建/删除窗口、为窗口分配其他缓冲区或改变尺寸。注意:即使已登记变更,也不代表上述钩子一定会运行。例如,某次变更登记在窗口暂存(excursion)范围内(see 窗口配置),则只有当该暂存在变更函数运行时仍有效,才会触发调用;若提前退出,则仅由暂存外的变更登记触发钩子运行。
一个 框架 的 窗口状态变更标记(window state change flag) 若被设置,将导致下一次重显示时运行该 框架 对应的 window-state-change-functions 默认值与 window-state-change-hook,无论该 框架 是否实际发生窗口状态变更。运行这些钩子上的函数后,各 框架 的该标记会被重置。应用程序可使用下列函数设置与查看该标记的值。
若 arg 非 nil,该函数设置 frame 的窗口状态变更标记,否则清除该标记。frame 必须为活跃 框架,默认为当前选中 框架。
若 frame 的窗口状态变更标记已设置,该函数返回 t,否则返回 nil。frame 必须为活跃 框架,默认为当前选中 框架。
在窗口变更函数运行期间,可调用下列函数以了解指定窗口或 框架 自上一次重显示以来发生了哪些变化。所有这些函数均接收一个活跃窗口作为唯一可选参数,默认为选中窗口。
该函数返回上一次为 window 所在 框架 运行窗口变更函数时,该窗口所显示的缓冲区。若返回 nil,表示该窗口是在此之后创建的;若返回 t,表示该窗口当时未显示,但之后从已保存的窗口配置中恢复而来。否则返回值为当时该窗口显示的缓冲区。
该函数返回上一次窗口变更函数检测到 window 在其 框架 上活跃时,该窗口的总像素宽度。若窗口在此之后创建,则返回 0。
该函数返回上一次窗口变更函数检测到 window 在其 框架 上活跃时,该窗口的总像素高度。若窗口在此之后创建,则返回 0。
该函数返回上一次窗口变更函数检测到 window 在其 框架 上活跃时,该窗口文本区域的像素宽度。若窗口在此之后创建,则返回 0。
该函数返回上一次窗口变更函数检测到 window 在其 框架 上活跃时,该窗口文本区域的像素高度。若窗口在此之后创建,则返回 0。
如需查看上一次运行窗口变更函数时哪个窗口或 框架 被选中,可使用下列函数:
该函数返回上一次运行窗口变更函数时,frame 的选中窗口。frame 省略或为 nil 时默认为当前选中 框架。
该函数返回上一次运行窗口变更函数时的选中窗口。
该函数返回上一次运行窗口变更函数时的选中 框架。
注意:窗口变更函数不会提供自上一次运行以来哪些窗口被删除的信息。如有需要,应用程序应在对应缓冲区的局部变量中记录显示该缓冲区的窗口,并在检测到窗口缓冲区变更的钩子默认值所运行的函数中更新它。
向窗口变更函数添加函数时应注意以下事项:
window-state-change-hook 默认值列表中的最后一个函数完成。
save-window-excursion、with-selected-window、with-current-buffer 等宏。
window-configuration-change-hook,否则也不会保存与恢复选中窗口、选中 框架 或当前缓冲区。